在 C++20 中获取当前 date/time 是线程安全的吗?
Will getting the current date/time be thread-safe in C++20?
小问题
在 C++17 之前(包括 C++17),C++ 没有提供线程安全的方法来获取当前时间或日期。这会在 C++20 中修复吗?
长问题
获取当前时间和日期的唯一可移植方法是使用 std::gmtime 或 std::localtime 函数。这些函数是 C 语言早期的残余,将自实现定义纪元以来的给定时间转换为日历时间(例如,1515153600 转换为 2018 年 1 月 5 日星期五 12:00:00 GMT)。然而,唯一的缺点是这些函数 return 是指向内部静态变量的指针并且不是线程安全的。更糟糕的是,这个静态变量可能会被所有相关函数共享,例如 std::gmtime、std::localtime 和 std::ctime,并且可能会在每次调用这些函数时被覆盖。因此,如果您正在使用线程并希望定期检查时间,您将面临数据竞争和未定义行为的风险。
显然,目前的标准在这方面已经被打破了。 C++ 标准委员会是否有任何努力来解决这种情况,以及它被包含在 C++20 中的可能性有多大?
Howard Hinnant 的 date library is what's coming for C++20. It was proposed via p0355r4 and approved for C++20 in Nov. 2017. Is it thread safe? Unfortunately, neither the documentation nor proposal seem to be clear on this. However, certain functions like get_tzdb_list
are explicitly said to have "Thread Safety". Your best option is to ask Hinnant himself in the gitter chat. However, discussion in Why is there no C++11 threadsafe alternative to std::localtime and std::gmtime? seems to suggest that it is thread-safe (even though it's never explicitly said). As Nicol Bolas 您可以将其包装在互斥锁后面。
If it doesn't you can again get data races and hence undefined behavior. If you're coding on large projects where coding work is divided into teams, you have to continously remind everyone that they should not (!) use the functions provided by the C++ standard, but use your own wrapper instead (or risk undefined behavior).
在浅层次上,这就是代码审查的目的。 Facebook 对于初级开发人员来说有这个问题,他们一遍又一遍地犯同样的错误。如果您的团队有 "curiously recurring bugs",您需要以某种方式解决它(比如向 linter 添加检查:想到 Clang)。
在更直接的层面上,Google 是这方面的缩影。他们遇到的问题是使用 string
的旧 COW 实现并切换到基于 SSO 的 string
。但是,由于他们依赖于使用基于 COW string
的第三方库,因此他们需要在其代码库中同时支持这两种库。告诉开发人员使用 Google 包装器是徒劳的。开发人员提出的解决方案是使用 inline namespaces
的 hack。有点极端,但如果您要处理类似的大型代码库,它可以解决问题。
小问题
在 C++17 之前(包括 C++17),C++ 没有提供线程安全的方法来获取当前时间或日期。这会在 C++20 中修复吗?
长问题
获取当前时间和日期的唯一可移植方法是使用 std::gmtime 或 std::localtime 函数。这些函数是 C 语言早期的残余,将自实现定义纪元以来的给定时间转换为日历时间(例如,1515153600 转换为 2018 年 1 月 5 日星期五 12:00:00 GMT)。然而,唯一的缺点是这些函数 return 是指向内部静态变量的指针并且不是线程安全的。更糟糕的是,这个静态变量可能会被所有相关函数共享,例如 std::gmtime、std::localtime 和 std::ctime,并且可能会在每次调用这些函数时被覆盖。因此,如果您正在使用线程并希望定期检查时间,您将面临数据竞争和未定义行为的风险。
显然,目前的标准在这方面已经被打破了。 C++ 标准委员会是否有任何努力来解决这种情况,以及它被包含在 C++20 中的可能性有多大?
Howard Hinnant 的 date library is what's coming for C++20. It was proposed via p0355r4 and approved for C++20 in Nov. 2017. Is it thread safe? Unfortunately, neither the documentation nor proposal seem to be clear on this. However, certain functions like get_tzdb_list
are explicitly said to have "Thread Safety". Your best option is to ask Hinnant himself in the gitter chat. However, discussion in Why is there no C++11 threadsafe alternative to std::localtime and std::gmtime? seems to suggest that it is thread-safe (even though it's never explicitly said). As Nicol Bolas
If it doesn't you can again get data races and hence undefined behavior. If you're coding on large projects where coding work is divided into teams, you have to continously remind everyone that they should not (!) use the functions provided by the C++ standard, but use your own wrapper instead (or risk undefined behavior).
在浅层次上,这就是代码审查的目的。 Facebook 对于初级开发人员来说有这个问题,他们一遍又一遍地犯同样的错误。如果您的团队有 "curiously recurring bugs",您需要以某种方式解决它(比如向 linter 添加检查:想到 Clang)。
在更直接的层面上,Google 是这方面的缩影。他们遇到的问题是使用 string
的旧 COW 实现并切换到基于 SSO 的 string
。但是,由于他们依赖于使用基于 COW string
的第三方库,因此他们需要在其代码库中同时支持这两种库。告诉开发人员使用 Google 包装器是徒劳的。开发人员提出的解决方案是使用 inline namespaces
的 hack。有点极端,但如果您要处理类似的大型代码库,它可以解决问题。