# gmtime_r 使用性?

## 故事

`gmtime_r` 很坑。

會用到 `gmtime_r` 的多少是因為 `gmtime` 不是 thread-safe 的，但又需要 threading 來增加效率。

但假如使用者會**很頻繁的呼叫他**，那就可能要考慮其他函數。

為什麼？

## `gmtime_r` 的運作

`gmtime_r` 的功能是把 Unix timestamp 轉換出 CST+0 時區的年月日時分秒以及其他資訊（如星期）。這個函數事實上會和 `localtime_r` 共用一個計算時間的函數。

這就是主要的問題，`localtime_r` 會需要用到時區資料，而【時區訊息與時間差】的資料並不是一直不變，由於夏令時間，這東西至少每年要更動兩次。

這函數在計算前，會**先去打開某個檔案，然後去更新一個全域變數。**

用來參考的 [Source Code](https://codebrowser.dev/glibc/glibc/time/gmtime.c.html)。

```c
/* Update internal database according to current TZ setting.
   POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
   This is a good idea since this allows at least a bit more parallelism.  */
  tzset_internal (tp == &_tmbuf && use_localtime);
```

沒錯，會去修改全域變數，然後又保證 thread-safe，那**通常**就有 **Lock** ，除非是 atomic 修改。

很直接的驗證方式，就是直接開一堆 Thread 去呼叫函數， htop 就可以看到近乎一半的 kernel mode，消耗時間也會隨開的 Thread 的數量快速增長。

## 可能的取代品

假如要保證 thread-safe ，又不希望有 Lock 影響到效能，可以考慮使用 Boost 的 [Posix Time](https://www.boost.org/doc/libs/1_54_0/doc/html/date_time/posix_time.html) 函數系列。

## Reference

* [gmtime C++ Reference](https://en.cppreference.com/w/c/chrono/gmtime)
    
* [gmtime Source Code](https://codebrowser.dev/glibc/glibc/time/gmtime.c.html)
    
* [localtime Source Code](https://codebrowser.dev/glibc/glibc/time/localtime.c.html)
    
* [Boost Posix Time](https://www.boost.org/doc/libs/1_54_0/doc/html/date_time/posix_time.html)
