WindowsのAPIうぜえ


 autoくれauto。何で今まで無かったんだauto。くれ。早くくれー。

 ああ、でも冷静になってみるとあれか。戻り値格納先のポインタを渡す類の関数にはもしかしてauto無理げじゃね。つーかWindowsそればっかじゃね。うぜえ(笑)。


FizzBuzz問題というのをやってみる


 調べ物でネットをふらふらしてたら、「プログラマの採用時にFizzBuzz問題ってのが便利です」とかいうのを見付けて、どんな問題だろうと思って恐る恐る見てみた。

1から100までの数をプリントするプログラムを書け。ただし3の倍数のときは数の代わりに「Fizz」と、5の倍数のときは「Buzz」とプリントし、3と5両方の倍数の場合には「FizzBuzz」とプリントすること。

 …え?

for ( 1..100 ) {
  print if $_ % 3 != 0 and $_ % 5 != 0;
  print "Fizz" if $_ % 3 == 0;
  print "Buzz" if $_ % 5 == 0;
  print "\n";
}

 こんな感じでいいんだよね?
 最初ちょっと仕様を読み間違えたけど気にしない(笑)。真面目に速度を出せ、とか言われたらもう少し悩みそうだけど。

 つーか、プログラマには本当に簡単に解けるのに、プログラマ以外にはえらい時間掛かったりするらしい。そういうものなのかー。面白いなあ。
 でも、俺が(何故か)採用する側になった時って確か、適当な二枚の絵をクロスフェードさせるコード書いてきて、とか言ったような気が。何でもいいんだよな。そして出来なかった人を採用した気もする(笑)。その人は確か半年後くらいにアドベンチャーゲームのシステム一本きっちり書き上げてたから問題無いよな。無いよね。


コンパイラ頑張れ超頑張れ


 いよいよこいつはSFINAEの出番か、と思ったけど、何かやっぱ新しい機能っぽい香りが漂いまくってるんでやめた。
 大体、アセンブラマクロみたいなC言語をベースにメタプログラミングとかまで取り込もうってんだから無理があるに決まってるんだ。無理と設計ミスだらけなのは分かり切ってるが、それがまた好きなんだという部分もあるかもしれない。386の仕様が286の影響でぐちゃぐちゃしてるのとか好きだしな。だが8086の64k境界は許さない。
 絵とかも、好みのタイプの人はもがいてるような絵が時々(または頻繁に)出てくるんだよなあ。完全に楽になっちゃってる人の絵は大抵面白くないっつーか即飽きる。ただ往々にして前者のタイプは悩みすぎて描かなくなるのだが。


メモリバリアうぜえ


 インデックス変数の書き換え前だけバリア張ってたけど、もしかして書き換え後にもバリア要るんじゃねーのかと思ったので書いた。まあ、状況的に恐らく両方とも書かなくていいんだが。
 あと、何でもかんでも_ReadWriteBarrier()じゃなくて、_ReadBarrier()や_WriteBarrier()も使い分けたい気もするんだけど、いまいちよく分かってないし。
 まあ現状だと吐くコードも変わらんのだし、必要になったら覚えよう。実際に必要な状況なら、適当にテストコード書いてコンパイル掛ければ簡単に覚えられるんだしな。


スレッド間通信飽きた


 何かここは速度要るもんらしいから、速度出るように頑張って書いてるんだけど飽きた。
 戻り値が欲しいとこなんて、演算要求投げてしばらく後に受け取り処理置いたり、とか8087臭がして扱いにくそうで困る。戻り値や引数の型をコンパイラが面倒見てくれないような世界に突っ込んでいいのかどうか。まー、やってしまえば問題無く書けるんだろうとは思うが。

 例のt2t_pipeは、pop()とpop_and_clear()を分けて、

  T pop () {
    assert( ! empty() );
    RMB();
    T result = buf_[index_to_pop_];
    index_to_pop_ = next_index_of( index_to_pop_ );
    WMB();
    return result;
  }
  T pop_and_clear () {
    assert( ! empty() );
    T result;
    RMB();
    { using namespace std;
      swap( result, buf_[index_to_pop_] );
    }
    index_to_pop_ = next_index_of( index_to_pop_ );
    WMB();
    return result;
  }

こんなんになった。PODなんかはpop()でいいし、shared_ptrみたいなのはpop_and_clear()で即削除させる感じ。クリアしたいかは色々な状況があるから、SFINAEで分けるのは無理。パイプクラス自体を二つ作る手もあるけど、まあこれでもいいだろ。
 出来れば、送信専用の関数は送信側にしか見えないような設計にしたいんだけど、思いつかなくてめんどくさいからしてない。デザインパターンとか勉強すりゃ出てくるのかなあ。まーいいか今はこれでも。
 これで大体完成なのかなあ。重くしたくないしなあ。呼び出し側がいちいち待機ループを組むのがめんどくさいが、バルク化する時は逆に楽そうな感じがする。
 リングバッファだからfull()なんかチェックしなきゃならないんだよ、って考え方もある。つまり標準のqueueかdeque辺りに突っ込めば、と。多分どうせスレッドセーフなコンテナではないから、full()が起きたらスレッドローカルなstd::queueに突っ込んでおく方式とかだな。
 うん。ボツだ(笑)。ぶっちゃけ、full()が起きるような状況になったら送信側はちょっと休んでろ。頻発するようなら共有パイプ小さすぎだろうし。アプリケーションによっては休み無く永久にpush()し続ける可能性もあるし。やっぱこのままでいいべ。

 んじゃ、t2t_pipe<int>でも作って、どう最適化されるか見てみようぜー。
 見てみた。大体ガチで削られてた。めでたしめでたし。t2t_pipe< shared_ptr<new T> >とかに比べたら雲泥のソレだな。
 だがメモリアクセスはそれなりに残るな…。別スレッドへの高速な通信ってメモリ以外無いよなあ。コア間のP2P通信レジスタとか無いですか。
 つーかそういう頑張るアプリ書いてる訳じゃないんだってのに俺は。まあ無駄なパズル遊びの癖は直らないんだろうなあ(笑)。