全ての意志決定者は一度株で大損こくべき

プログラミングとは直接関係ないですが、営利組織の舵取りに不可欠な意思決定について。

さてさて自分は投資については全くの素人なのですが、その世界ではわりと有名なプロスペクト理論(元は行動経済学の概念だそう)というのがあります。簡単に言うと

・人間は目の前の利益が手に入らないというリスクの回避を優先し、損失を目の前にすると損失そのものを回避しようとする。

と言う事だそうです。つまり、自分自身の意思決定がこのプロスペクト理論によって支配されていると言うことを客観視出来ない人は、「上昇中の株価が反転するのが怖くて早々に売却してしまう」「値下がり中の株の含み損が売却によって確定するのを躊躇し、いたずらに損失を拡大させてしまう」という利益を上げるといった観点では逆の不合理な行動をとってしまいます。

さて、これは投資に限った話ではなく企業で行われる意思決定においても非常に似たようなケースがあるのではないでしょうか。例えば

・商談中の顧客が明らかに割に合わない要求をしてきているのに、失注を恐れて強気に交渉したり、切ったりすると言うことができない。
・新規事業がずっと赤字を垂れ流しているのに、今まで投資した経営資源を考え撤退ができない。

意思決定者がこれらの責任を全面的に取ってくれれば良いのですが、残念ながらここで生じた歪は現場に降りてきます。その挙句の、激務、長時間労働、デスマーチと言うのはもう鉄板と言っても良いぐらいお決まりな流れな気がします。

そういうのを考えると、やはり一度個人的に株で大損こいて、その理由についてきちっと消化&対策出来ている人の方が良いマネージャーや良い経営者になる可能性が高いような…

(そんなん無理やろと言うツッコミは置いておいて)少なくとも自分はそういう人の下で働きたいですね。

C++ std::regex_token_iterator で文字列を split (token 分解)

完全に boost ::tokenizer 相当と言うわけでは無いですが、C++11 から追加された正規表現ライブラリに std::regex_token_iterator  と言うイテレータが含まれており、これを文字列の split に利用する事ができます。

std::regex_token_iterator (cppreference.com)

詳細については上記のリンクを見ていただくとして、std::regex_token_iterator の基本的な使い方は以下のようになります。

上記の例を見て頂ければ分かると思いますが、コンストラクタの第4引数に正規表現でキャプチャした文字列のうちどのインデックスのものをイテレーション対象にするかを指定します。インデックスには 0 と -1 を指定することが可能で、0 を指定した場合はマッチした文字列全体が、-1 を指定すると対象の文字列全体からマッチした部分を取り除いた断片がイテレーションの対象になります。

この「マッチした部分を取り除いた断片をイテレーションする」と言う機能を利用すると split 処理を書く事ができ、例えば

のようになります。

ただ処理速度的にはアレだと思いますので、速度が要求される場面では従来から行われている愚直な処理の方がマッチするのではないかと思います。

 

C++ で Future パターン

Future とはスレッドで実行している処理との同期、スレッドからの結果の受領を行うためのパターンです。Future パターンは C++11 から std::future という形で標準ライブラリで提供されていますので、具体例については  cppreference.com  などをご参照下さい。

C++ でマルチスレッドデザインパターン

 

C++ で Worker Thread パターン

Worker Thread とは一般に生成、破棄コストの高いスレッドをプールして使い回すためのパターンで Thread Pool とも呼ばれます。 Worker Thread パターンは Producer-Consumter パターンに基づいており、キューで受け渡されるのがデータではなく実行可能な仕事を表現したオブジェクトである点が特徴です。

以下の例で Runnable は仕事の基底クラスであり、std::shared_ptr<Runnable> のキューをを介してプールされているスレッドに仕事を依頼します。 クライアントは Runnable のサブクラスを作成し、インスタンスをスレッドプールに add する事で自分でスレッドをハンドルする事無く非同期に仕事を実行させる事ができます。

実際に使用してみると以下のようになります。 以下の例では WorkA, WorkB という異なる2つの内容の Runnable サブクラスのインスタンスを add しています。 仕事は Runnable で抽象化されていますので WorkA、 WorkB 以外にも任意の仕事を実行させる事が可能です。

Runnable のような基底クラスではなく特定の仕事クラスのキューを持たせる事も可能ですが、より汎用的にするためにこのようにするケースが多いように思います。また C++11 からは std::function が利用できますので、std::function のキューにするとより C++ っぽいかもしれません。

std::function 版の使用例です。

C++ でマルチスレッドデザインパターン

C++ で Producer-Consumer パターン

Producer-Consumer とはデータを生産する Producer スレッドとデータを消費する Consumer スレッドがキューを介してデータをやり取りするパターンです。

以下の例では、Producer 側からキューに追加された文字列を Consumer スレッドで取り出して標準出力に出力しています。

Producer スレッドはキューにデータを積む際に Consumer スレッドを起床させ、Consumer スレッドはキューが空になるとブロックされ sleep 状態に入ります。この動作は Garded Suspension パターンそのもので、Producer-Consumer パターンは下位レベルで Garded Suspension パターンを利用していると言えます。 (実際以下の例も Garded Suspension パターンで挙げた例と殆ど同じ内容ですが、スレッドが複数になっている点が異なります)

実際に使用すると以下のようになります。

今回は Producer 側はメインスレッド1つのみですが、当然 Producer 側が複数スレッドになるパターンもあり得ます。

ちなみに上記の例でもスレッドをお行儀良く終了させるために  Two-Phase Termination パターン を併用しています。

C++ でマルチスレッドデザインパターン

C++ で Two-Phase Termination パターン

Two-Phase Termination とは外部からスレッドに対して終了要求を送り、スレッドが自身のタイミングの良い所で処理を終える事で安全にスレッドの終了を行うためのパターンです。

C++ の std::thread ではスレッドを強制終了させるような手段は用意されていないようですが、一般に Two-Phase Termination を行わずに外部からスレッドを強制終了するなどした場合、データの不整合や、リソースリークなどが発生する可能性がありますので大変重要なパターンだと思います。

C++ でマルチスレッドデザインパターン

C++ で Guarded Suspention パターン

Guarded Suspention とは、ある条件が整うまでスレッドの実行を block するというパターンです。 C++ の標準ライブラリで condition variable が提供されていますので、そのまま Guarded Suspention パターンに利用することができます。

以下の例はキューに追加された文字列をスレッドで取り出して標準出力に出力する例です。 Printer というクラスが内部にスレッドを有しており、append で文字列が追加された際にスレッドを起床させて処理をさせます。スレッド側はキューが空になるとブロックされて sleep 状態に入ります。

実際に使用すると以下の用になります。

実装的な注意点として C++ ではメンバー変数の初期化は初期化リストの記述順ではなく宣言順に行われるため、上記の例では std::thread のメンバーの宣言は最後に行うようにする必要があります。スレッドの動作は初期化リストでコンストラクトされた直後に開始されるため、うっかりスレッドが触っているメンバー変数の宣言をスレッドインスタンス宣言の後に行ってしまうとタイミングによって未初期化変数へのアクセスが発生してしまいます。

ちなみに上記の例ではスレッドをお行儀良く終了させるために  Two-Phase Termination パターン を併用しています。

C++ でマルチスレッドデザインパターン