最終更新: 2013-07-14T00:41+0900
静的変数の初期化とマルチスレッド安全性。C++11より前と VCに関してはお寒い状況らしいが、そもそものコードが素朴なものだった。
もともとマルチスレッド対応ではないので静的変数で実装するのは大差ないとして(マルチスレッド対応コードを自分自身で書く機会を放棄することにはなる?)、唯一性の保証を TSingleton利用者に期待するというなら TSingletonはただグローバルアクセサを定義する手段になってしまう。この assertで従来通りの保証ができるかなと思ったんだけど
TSingleton(){ assert(this == static_cast<TSingleton<T>*>(T::getInstance())); }
static変数の初期化にロックがかかってたらこれはデッドロックを引き起こすんでない?ロックせず素通りしてしまうと未初期化オブジェクトを使用してしまうおそれがあるよね? C++11に対応した gccはどうやってるんだろ。
パッチの目的はデストラクタが呼ばれるようになることにあるらしいが、一方で、任意のタイミングでオブジェクトを破棄することはできなくなる。それはシングルトンオブジェクトにはそぐわない扱いかもしれないけど。
本当に stackoverflowのコードを利用するなら継承をやめたらいい。そうすれば TSingletonの利用者などというものは存在せずシングルトンクラスの実装者しかいなくなる。実装を提供するだけならマクロでもできるし、あえて継承にする理由は一元的にインスタンス作成を補足することではないかと。偽りの名前を与えられた中途半端な実装を別ファイルに隔離するのはどうかと思う。
3回ぐらいコメントの下書きをしてるけどぐるぐるしてまとまらなくてこの日記になる。
インスタンス変数を関数内staticではなくクラス内staticにするとアドレスを取得するのに getInstanceを呼ぶ必要がなくなって、getInstanceとコンストラクタ呼び出しがネストしなくなってロックの可能性(そんなものが実在するかは gccがないので知らない)が消える、と思ったんだけど、すべてのシングルトンオブジェクトの初期化がプログラム起動時に走ってしまいそうだ。これを避けるとインスタンスをポインタで保持することになって、これは現在のコードだ。インスタンスを関数内staticで保持したまま、getInstanceでそのアドレスだけをクラス内static変数にコピーする、とかいうのはトリッキーなわりに利がなくて目的を見失ってる感。
クラスで実装するシングルトンってなんのためにあるんだろうね。アプリケーションクラスだけがシングルトンでそれ以外はそのメンバでいいやん。Javaとか C#の Main関数みたいな居心地の悪さがあるかしらんけどさ。
同じスレッドであれば同じCRITICAL_SECTIONを引数にして何度でも EnterCriticalSectionできるらしい(同じ回数の LeaveCriticalSectionが必要)。
各スレッドはクリティカルセクションの所有権を取得した後は、自らの実行をブロックすることなく、EnterCriticalSection または TryEnterCriticalSection 関数を追加で呼び出すことができます。この結果、スレッドが既に自ら所有しているクリティカルセクションを待機しようとしてデッドロックに陥ることを防止できます。
というわけで、コンパイラが静的変数の初期化を実際どう実装するかは知らんけど、あまり気にせず上の方に書いた assertを使っていいんじゃないかな。
イベントを使ったのはこのとき(20130416)が初めてで、クリティカルセクションはまだ使ったことがないのでした。たぶんその存在はペゾルドさんの本で読んだんだろうなあ。9年前。
最終更新: 2013-07-24T20:03+0900
年末から 3Dゲームを始めると BSODが出ていた。メモリテストでハードウェアエラーが見つかったので新品に交換したが、ましになったもののまだ出る。ブルースクリーンの原因は3、4種類あって、ドライバが原因というよりはメモリの内容が化けて暴走してるのではないかと思われる。それもスリープ(S3)復帰後が鬼門で、一度 BSODが出て再起動してしまうともう大丈夫だったりした。
そんなんでだましだまし使ってた。Catalystをアップデートしたり、メモリテストを実行してみたり(エラーは出ない)、スリープから復帰してから数時間は負荷をかけないとか。最近の BSODはすべて PAGEFAULT_IN_NON_PAGED_AREAが原因になっていた。PCゲームはここのところ起動してないのでブルースクリーンは専ら自炊後の PDF作成フェイズで起こる。ChainLPが画像処理を7枚並行で行っていて 3Dゲームに次ぐ負荷。8GB積んでる RAMのうち 6GBくらいは(ディスク?)キャッシュに使われていて、これが化けてるせいでキャッシュを取り崩す際に問題が発覚するんじゃないかとか想像してた。ところが暑さのせいなのかなんなのか、とうとう再起動しても再起動しても PDFを作成しようとするとブルースクリーンが出るようになった。キャパシタ(コンデンサ)が用を為さなくなってるんだろうか。これでは夏を乗り切れない。一枚目星を付けていたのがあるんだけど、SocketAM3なので新しくも安くもなくてできれば買わずに済ませたかった。
MSI AMD990FX+SB950チップセット搭載 AM3+対応メインボード 990FXA-GD80
MSI COMPUTER
¥ 13,090
東芝サムスン DVD-RAM/±R(1層/2層)/±RW対応 SATA接続 5インチベイ DVDドライブ SH-224DB+S
東芝サムスン
¥ 1,979
SANWA SUPPLY シリコングリス TK-P3S
サンワサプライ
¥ 490
ケースのフロントパネルに IEEE1394端子があり、また不運なことにそこに繋がってしまう 3G iPodがまだ手元にあるので、内部IEEE1394ピンヘッダを条件に加えたら選択肢がほとんどなくなってしまった。
さすがに FDDコネクタと IDEコネクタまで要求してしまうともう選べるものがないのでこちらは妥協する。フロッピーは XPのときに RAIDドライバのインストールに使ったりしたものの Vistaでは USBメモリという選択肢もありもはや使わないが、IDEは光学ドライブが必要としている。変換基板が1500円だったのでわずか500円高の SATA光学ドライブそのものを買ったけど、ゴミが出るのが(ゴミにせずとっておくのも!)気に入らない。<追記@2013-06-27>CDを取り込むために初めて使用したんだけど、CD2WAVは進捗状況を表示してるんだけど、顔を 20cmまでケースに近づけても CDが回転してるのかファンの音が漏れ聞こえてるのか区別がつかない。これは感動だ。2005年のものとは比較にならねえ。</追記>
これで直らなかったら涙目。
S3の消費電力が 2.5Wから 1.8Wに減ったのと、S4と S5からもキーボードで復帰できるらしいのだけが改善点。期待されるベストが去年までの 790FX-GD70の環境を再現することなので 990FXA-GD80に罪はないが*。M/B入れ替えの影響がちょぼちょぼと。Vistaの認証をするために MSの自動音声に3回目の電話。SpeedFanが起動中にシステムを巻き込んで何分もフリーズするが speedfanparams.cfgを削除したら直った。DSC-HX30Vの Wi-Fi取り込みがうまくいかない。ネットワークには現れるがコンピュータに出現しない⁑。M/Bに接続した5つのファンのうち SYSFAN4の回転数の読みと制御だけができていない。昨日はできたと思ったし、センサーや設定が共通の SYSFAN3はうまくいってるので機械的な問題かも。vclock祐巳の時刻の読みにリバーブがかかってる。再生デバイスのひとつを無効化したからかなんなのか今のところ直ってる。COSMOSのフロントパネルが、コネクタの機能確認のため USBメモリを抜き差ししてるうちに陥没した。ネジ4本でコネクタ部が裏から固定してあるのだけど3本のネジ穴が割れてた。接着剤でくっつけようと手に持つそばから砕けていくのだから素材が悪い。こんなところ。負荷テストはまだ。写真を撮ったけどさっき書いたように転送できてない。
涙目。動画を再生してるだけで例の PAGEFAULT_IN_NON_PAGED_AREAが出た。強制終了を繰り返してるうちに OSのファイルが壊れたか、CPUか、GPUか。SSDを買って OSをクリーンインストールするかエアコンを付けるかした方が有意義だった。
<追記@2013-06-17>最新の BIOS(v11.13, 2012年の9月か10月)が最初から入ってたんだけど、不具合。スリープ(S3)に移行した後は SYSFAN4の回転数がとれなくなる。SpeedFanだと 366RPMという嘘の数値で固定される。MSI Control Centerだと 0RPMと表示される。隣のSYSFAN2と配線を入れ替えてみるべきか?</追記>
<追記@2013-07-24> ブルースクリーンはすぐ上に書いた1回しか出ていない。CPU温度に注意してるのが良いのだろうか。AMD K10が報告する温度は Radeonが報告する温度と比べて 15-20℃くらい低めなのだ。体温より低いってありえない。BIOSで設定する、そういう温度をベースにした CPUファン回転数のスマート制御はずっと機能不全だったのだろう。V8(CPUファン)は回転数を調節するつまみを外出しするブラケットが付いているので夏と冬に手動で調節することにする。 </追記>
風が常に吹きつける CPUクーラーと DrMOSのフィン以外はきれいじゃないかな。
真上に持ち上げようとしてできなくてあれこれ持ち替えながら力を加えてたら CPUごともげて肝を冷やした。IvyBridgeでもなければ(Haswellもらしい)殻割りなんてしたくない。密着してるので横にずらすべきだった。
* 内部SATAポートが8から6に減ったのは理解できない。6ある HDDベイに割り当てたらフロントパネルの eSATAポートはもちろん光学ドライブに割り当てる分も余らないではないか。IDEを廃止しておいてこれか?代わりに USBコネクタが余ってるけど、USBばっかりいらないんだよ。なんでもかんでも USBで間に合わせようという雑な考えが気に入らない
⁑ PlayMemories Homeで Wi-Fi取り込みの設定をリセットするつもりで再度行っていたのだけど、設定はそれだけでは不足で、カメラを一度 USB接続する必要があった。そうすると Wi-Fi接続可能なカメラがあるがこれをこの PCと関連付けるか?という選択肢を PlayMemories Homeが表示した。そうだよなあ。そうじゃないと DSC-HX30Vは同一ネットワーク内のすべての PCから要求されるがままに画像を漏らすことになるもんなあ。説明書の Wi-Fi取り込みの項を読んでもそんな手順は書いてなかったけどな。あと、新しく取り込んだ画像が反映されなかったのでデータベースの再構築をする必要があった。ネットワークインターフェイスが変わった影響かは知らない。あと、カメラの IDのうち「&0&」の部分が「&1&」に変わってた。