-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use std::shared_mutex in time_zone_impl.cc #304
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
#include <deque> | ||
#include <memory> | ||
#include <mutex> | ||
#include <shared_mutex> | ||
#include <string> | ||
#include <unordered_map> | ||
#include <utility> | ||
|
@@ -33,10 +34,10 @@ using TimeZoneImplByName = | |
TimeZoneImplByName* time_zone_map = nullptr; | ||
|
||
// Mutual exclusion for time_zone_map. | ||
std::mutex& TimeZoneMutex() { | ||
std::shared_mutex& TimeZoneMutex() { | ||
// This mutex is intentionally "leaked" to avoid the static deinitialization | ||
// order fiasco (std::mutex's destructor is not trivial on many platforms). | ||
static std::mutex* time_zone_mutex = new std::mutex; | ||
static std::shared_mutex* time_zone_mutex = new std::shared_mutex; | ||
return *time_zone_mutex; | ||
} | ||
|
||
|
@@ -58,7 +59,7 @@ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { | |
|
||
// Check whether the time zone has already been loaded. | ||
{ | ||
std::lock_guard<std::mutex> lock(TimeZoneMutex()); | ||
std::shared_lock<std::shared_mutex> lock(TimeZoneMutex()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you are seeing contention on this mutex, which is only held over an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem is that our functions will take an optional timezone parameter (string) from the user input. We need to have a mechanism to load it once and store it somewhere (we probably want to avoid using lock again on a map). I am thinking to have a static map <name, timezone> to pre-load all time zones which is not ideal and seems to waste space since most timezones are not used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
My suggestion would be to change that type from a string to a
Alternately, introduce your own "timezone" type and factory (if you don't want Or, you could keep your string parameter, but have some variety of internal static map, which, again, is not pre-loaded but rather filled on demand. In each case, the thread safety requirements of the map would be determined by the thread safety of your interfaces. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks a lot for suggestions. I will think a bit more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not only is that simpler and gives the user control over when zones are loaded, it would also save you from having to deal with load failures. Good luck. |
||
if (time_zone_map != nullptr) { | ||
TimeZoneImplByName::const_iterator itr = time_zone_map->find(name); | ||
if (itr != time_zone_map->end()) { | ||
|
@@ -72,7 +73,7 @@ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { | |
std::unique_ptr<const Impl> new_impl(new Impl(name)); | ||
|
||
// Add the new time zone to the map. | ||
std::lock_guard<std::mutex> lock(TimeZoneMutex()); | ||
std::unique_lock<std::shared_mutex> lock(TimeZoneMutex()); | ||
if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName; | ||
const Impl*& impl = (*time_zone_map)[name]; | ||
if (impl == nullptr) { // this thread won any load race | ||
|
@@ -83,7 +84,7 @@ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { | |
} | ||
|
||
void time_zone::Impl::ClearTimeZoneMapTestOnly() { | ||
std::lock_guard<std::mutex> lock(TimeZoneMutex()); | ||
std::unique_lock<std::shared_mutex> lock(TimeZoneMutex()); | ||
if (time_zone_map != nullptr) { | ||
// Existing time_zone::Impl* entries are in the wild, so we can't delete | ||
// them. Instead, we move them to a private container, where they are | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry, but requiring C++17 for CCTZ is a non-starter (at least in the medium term).