スレッドセーフティな時間

同期を取るタイミングがどうとかいう話しではなくて。

以前Windowsの標準C++ライブラリではctimeがincludeされる名前空間が間違っている、と書いたけれども、それをさしおいてもWindowsで時間を扱うプログラムをする場合はAPIを使ったほうがいいという根拠を書いておく。

ctime、厳密にはtime.hで定義されている時間を扱う関数の中で、

  • asctime()
  • ctime()
  • gmtime()
  • localtime()

は現在あまり使うべきでない、と言われている。スレッドセーフティではない関数だというのが唯一にして最大の理由だと思われる(個人的にはポインタを返す関数は内部で何をやってるかわからないので信用できない。)が、POSIXでは代替案というか実質的にこれらに取って代わっているのが、末尾に_rがついた以下の関数だ。

  • asctime_r()
  • ctime_r()
  • gmtime_r()
  • localtime_r()

確かにこれらを使えば問題はない…、のだが上記の関数は標準規格のようで標準規格でないctimeのLinux版manpageによるとBSDでこういった拡張が行われたようだ。あくまでもPOSIXで行われた拡張なので、Windowsでは使うことができない。どうしてもスレッドセーフティに時間を扱おうとするとGetLocalTime()などのAPIに頼らざるを得ない。

上記の問題はC/C++標準で用意されている関数だけでは時間を扱う処理を行えない、ということを示唆している。つまり、Windows<-->POSIXで移植性の高いプログラムを書こうとすると、どうしてもプリプロセッサで場合分けしなければならなくなる(他にも弊害はあるかもしれないが)。元凶はC標準規格であるtime.h内で定義されている関数が腐っている、ということに尽きるのだと思うが、途中でC標準を見直す機会とかなかったんだろうか?Cでは互換性の問題で難しくてもせめてC++ではきちんとした関数を提供する、とか。

boost::date_timeはまだ本格的に使ったことがない。が、見た限りでは純粋な時間の計算を行う上では問題ないと思うんだが、ファイルの更新時刻を処理したい等、ファイルシステム絡みになると手に余ることがあるので(特にFileTimeToDosDateTime等に代わるDOSタイムの処理は今後も期待できないだろう、というかそんな限定的な機能標準にはいらないね)、「んー…。」と言った状況。

時間処理とかいって実は大事なのに一番面倒な部分になってる現状はどうなのよ?