Thread safe, cross platform std::localtime()

Hi everyone,

I'm in need of a thread safe and cross platform solution for std::localtime() (a way to convert std::time_t into std::tm). The reason is that I'm using a library that only allows for std::tm, but I prefer to use std::time_t because it is compatible with C++11's <chrono> library.

From what I gather there are some platform dependent alternatives, such as posix::localtime_r(), but no cross platform way.

I don't mind writing my own, but I would need help getting started in that case.More particularly I can't figure out how to convert a std::time_t into years/months/days etc. because the epoch is not the same on all platforms, and so I don't really know what number to base calculations on.

Edit: the code would be part of the library, so I have no control over clients calling std::localtime themselves.

Any ideas / suggestions would be greatly appreciated, as always.

All the best,
NwN
Last edited on
Maybe you're overcomplicating this?


Thread-safe, crossplatform std::localtime:

1
2
3
4
5
6
7
8
9
10
11
namespace
{
  std::mutex time_mutex;
}

tm localtime(const time_t * timer)
{
  std::lock_guard( time_mutex );
  tm ret = *std::localtime(timer);
  return ret;
}
Hi Disch,

Overcomplicating does sound like me, I'm also not too familiar with concurrent programming (yet).

Could you please explain how the time_mutex protects the static internal "tm" which std::localtime sets?
From what I understand, the mutex will prevent more than one thread from running your localtime() function at the same time.

But what if someone decides to call std::localtime directly in another thread, wouldn't that alter the static internal "tm" used by std::localtime, std::gmtime, etc.?
The code would be part of a library, so I don't have full control over the resulting program (probably should have mentioned that from the get-go, sorry).

Just trying to understand and learn.

Thanks for your help!

All the best,
NwN
Could you please explain how the time_mutex protects the static internal "tm" which std::localtime sets? From what I understand, the mutex will prevent more than one thread from running your localtime() function at the same time.


That's all there is to it. std::localtime can be called from any number of threads just fine, as long as it's only being called from one thread at a time.


But what if someone decides to call std::localtime directly in another thread, wouldn't that alter the static internal "tm" used by std::localtime, std::gmtime, etc.?


Yes. If you call a function that is not threadsafe in a threaded environment, you will have undefined behavior.

The code would be part of a library, so I don't have full control over the resulting program (probably should have mentioned that from the get-go, sorry).


Ah... that does change things. Admittedly the above solution was less than ideal... it was just the simplest.
Compile-time optioning for POSIX and Microsoft:

1
2
3
4
5
6
7
8
9
10
11
12
namespace util
{
    inline std::tm localtime( std::time_t t )
    {
        #ifdef _MSC_VER >= 1400 // MSVCRT (2005+): std::localtime is threadsafe
            return *std::localtime(&t) ;
        #else // POSIX
            std::tm temp ;
            return *::localtime_r( &t, &temp ) ;
        #endif // _MSC_VER
    }
}


Awesome JLBorges, I'll need to read up on those compiler specific preprocessor directives.
Thanks a lot :)

All the best,
NwN
Topic archived. No new replies allowed.