何かここは速度要るもんらしいから、速度出るように頑張って書いてるんだけど飽きた。
戻り値が欲しいとこなんて、演算要求投げてしばらく後に受け取り処理置いたり、とか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通信レジスタとか無いですか。
つーかそういう頑張るアプリ書いてる訳じゃないんだってのに俺は。まあ無駄なパズル遊びの癖は直らないんだろうなあ(笑)。