7

The title says it all.

I have to implement a function that receives a std::chrono::system_clock::duration value and that needs to convert it into a timeval sruct so I can pass it to some system function.

Laurel
  • 5,965
  • 14
  • 31
  • 57
chmike
  • 20,922
  • 21
  • 83
  • 106

2 Answers2

9

More general implementation.

template<typename Duration>
void to_timeval(Duration&& d, struct timeval & tv) {
    std::chrono::seconds const sec = std::chrono::duration_cast<std::chrono::seconds>(d);

    tv.tv_sec  = sec.count();
    tv.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(d - sec).count();
}

UPDATE:

Separate methods like to_timeval() are not too convenient. Where is overloading power? We have just hardcoded type timeval into name of function to_timeval(). It's not C++ way. I want to pass struct timeval into, for example, std::chrono::duration_cast() and get my chrono-result and vice versa.

So, we can extend std::chrono::duration_cast (of course, at your own risk). Enjoy.

namespace std {
namespace chrono {
namespace detail {

template<typename From, typename To>
struct posix_duration_cast;

// chrono -> timeval caster
template<typename Rep, typename Period>
struct posix_duration_cast< std::chrono::duration<Rep, Period>, struct timeval > {

    static struct timeval cast(std::chrono::duration<Rep, Period> const& d) {
        struct timeval tv;

        std::chrono::seconds const sec = std::chrono::duration_cast<std::chrono::seconds>(d);

        tv.tv_sec  = sec.count();
        tv.tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(d - sec).count();

        return std::move(tv);
    }

};

// timeval -> chrono caster
template<typename Rep, typename Period>
struct posix_duration_cast< struct timeval, std::chrono::duration<Rep, Period> > {

    static std::chrono::duration<Rep, Period> cast(struct timeval const & tv) {
        return std::chrono::duration_cast< std::chrono::duration<Rep, Period> >(
                    std::chrono::seconds(tv.tv_sec) + std::chrono::microseconds(tv.tv_usec)
                    );
    }

};

}

// chrono -> timeval    
template<typename T, typename Rep, typename Period>
auto duration_cast(std::chrono::duration<Rep, Period> const& d)
-> std::enable_if_t< std::is_same<T, struct timeval>::value, struct timeval >
{
    return detail::posix_duration_cast< std::chrono::duration<Rep, Period>, timeval >::cast(d);
}

// timeval -> chrono
template<typename Duration>
Duration duration_cast(struct timeval const& tv) {
    return detail::posix_duration_cast< struct timeval, Duration >::cast(tv);
}

} // chrono
} // std

It's just example. As alternative we can implement own duration_cast() and in some cases forward it into std::chrono::duration_cast().

And we remember about struct timespec.

Nevermore
  • 1,127
  • 9
  • 12
  • 1
    Awesome answer! (For the benefit of other readers) The reason this answer is superior is that it has no manual conversion factors. It leverages the chrono library to do the conversions. – Howard Hinnant Sep 24 '15 at 15:26
5

Let d be the input duration value and tv the output timeval structure filled by the convert function. Note: the function sets the timeval to 0 if the duration is negative.

void convert( const std::chrono::system_clock::duration &d, timeval &tv )
{
  chrono::microseconds usec = chrono::duration_cast<chrono::microseconds>(d);
  if( usec <= chrono::microseconds(0) )
    tv.tv_sec = tv.tv_usec = 0;
  else
  {
    tv.tv_sec = usec.count()/1000000;
    tv.tv_usec = usec.count()%1000000;
  }
}
chmike
  • 20,922
  • 21
  • 83
  • 106