cutlassfish について

Embedded をバックグラウンドに持つ似非組み込みエンジニア。 現在はとある Web 系企業のバックエンドエンジニアをやってます. 気づけばもうすぐ 34 に... アラフォー目前...

C++ で Read-Write lock パターン

同じデーターに対して複数のスレッドが入り乱れて読み書きを行う場合、排他のオーバーヘッドが無視できずに問題になることがあります.

そこで Read アクセスのみの場合は排他を行わなわず、Read-Write がかち合った場合にのみ排他を行うことでオーバーヘッドの低減を図ろうというのがこのパターンです.

Read-Write lock パターンは shared mutex という形で標準ライブラリで提供されています (shared mutex の詳細については以下のリンクを参照下さい)

cppreference

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

C++ で Thread-Specific Storage パターン

複数のスレッドから読み書きされるデータはその内容の整合性を保つため、基本的には排他処理を行う必要があります(Single Thread Execution パターン

Thread-Specific Storage パターンは同じデータに複数スレッドからアクセスが行われ、かつスレッド間でのデータの共有が不要といったケースにおいて、スレッド毎に専用の領域を用意する事で排他を行わずに並列実行可能なようにすると言うパターンです.

C++11 から、新たな記憶クラス指定子として thread_local というものが用意されており、これを使うと簡単に Thread-Specific Storage パターンを使うことができます (thread_local 記憶クラス指定子についての詳細は以下のリンクを参照下さい)

cppreference

このパターンの実際の使い所ですが、積極的に使用するケースというのはあまりなく、「シングルスレッドでの使用を前提に静的領域を多用している(場合によってはレガシーな)コードを比較的簡単にマルチスレッド化する」といったような用途で使用される事が多いような気がします.

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

MacOS Sierra 10.12 + Xcode 8 + Qt 5.9.1 で QMake 時に「could not resolve SDK Path for ‘macosx’ 」 エラーになる問題

転職直後の大変さもだんだん落ち着き、念願叶って開発環境もWindows から MacOS & Linux になったので 「よし Mac に Qt の開発環境を準備しよう!」と思い立ってハマりまくったお話.

開発環境を作ると言っても、いつも通りインストーラー落としてきてインスコするだけだろうと思ったら QMake 時に「could not resolve SDK Path for ‘macosx’ 」と言って怒られてしまう…

最初にこんな物を見つけて、やってみるけどダメ…
https://stackoverflow.com/questions/26320677/error-could-not-resolve-sdk-path-for-macosx10-8/26321074

困り果てて、ダメ元でもう一度インストールしてみると Xcode 5.0.0 を入れろと警告してくる.  最初は「Xcode ? あぁー後で入れる入れる」と適当に流していたんですが、「Xcode 5.0.0 !? どんだけ古いねん! うぇーもしかして Qt の MacOS への対応ってすごい遅れてる???」とか思って、Apple の developper サイトから Xcode 5.0.0 を落として来てみるも、古すぎて Sierra にはそもそも入れられない…

転職でキャリアチェンジして仕事で Qt を弄らなくなってしまったというのもあり、その後も暫く空き時間やプライベートの時間に試してはダメを繰り返して、今日以下のポストを参考にやっと解決しました.

https://stackoverflow.com/questions/41513456/qt-5-7-xcode-8-1-os-x-el-captain-could-not-resolve-sdk-path-for-macosx

結果的に Xcode 上から一度どの Command line tool を使用するかの選択をしないと、Qt が参照している PATH 系の何かがセットされないような感じっぽい??

まさかこんなにどハマリするとは予想していませんでしたが、 とにかく情報が全然出てこないので Mac の Qt develper にはもしかして常識なのか、Xcode での開発をガン無視して初っ端から Qt で開発しようとしている自分がアレなのか…

ともかく毎度の事ながら stackoverflow さまさまでした… ありがたい

C++ で Thread-Per-Message パターン

Thread-Per-Mesasge パターンとは時間を要する処理要求に対し、一つ一つスレッドを割り当てる事で応答速度の向上を目的とするパターンです.

例えば以下は時間のかかるファイル保存の処理に Thread-Per-Message を適用した例です.

ここではダミーで標準出力へ出すようにしていますが、 Helper は処理の本体であるファイル保存を行うクラスで Host は client からの要求を受け、処理を行うスレッドを起動するクラスです.  スレッドはインスタンス化と同時に detach され、Host とは完全非同期に処理を実行します.(上記のような簡単な例だと Helper を利用するのが大げさに感じてしまいますが、本来のパターンに忠実に従い上では Helper を定義しています)

さてこの Thread-Per-Message パターンですが、実は使い所が大変難しいパターンだと思います.  なぜ難しいかと言うと スレッドは生成と同時に detach されて生成元のあずかり知らないところで動作を行うため、生成元で処理の終了やエラーの発生を感知できないからです.

では逆にどんな処理なら問題無いかと言うと

(1) 絶対エラーが発生しない (もしくは発生しても問題ないと) と分かっている単純な処理.
(2) deadlock 等が発生せず、一定の時間で終了することが保証されている処理.
(3) スレッドで実行される処理が非同期に動作するプログラムとして高い独立性を持っており、エラー処理等を完全に自己で完結出来る場合.

の場合のどれかに当てはまる場合でしょう.  (1) は言うまでも無いと思いますが、(2) の場合 deadlock を起こしたスレッドが開放されない事で徐々に OS のリソースを食いつぶして行き、最終的に処理速度の低下やスレッド生成の失敗等につながる恐れがあります.  (3) は Apache 等の Web サーバーがリクエストを捌く際に行う処理がまさにそれです (Apache の場合はリクエスト毎にスレッドでは無くプロセスを起動するので Process-Per-Message というのが正しいですが..)

というわけで今回取り上げたファイルに保存すると言う例も、ログファイルなどの「まぁ、問題が起こったら保存されなくてもしょうがないよね」というような用途以外で使用するのは適切ではありませんのでご注意を.

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

 

C++ で Balking パターン

Balking パターンとは「オブジェクトに対しての処理要求に対し、オブジェクトが特定の状態にある場合にのみ処理を行う(そうでない場合は何もしないで抜ける)」というパターンです。

例えば GUI システムでは多くの場合 main スレッドが UI のイベントループをハンドルしているため、lock 待ち等で main スレッドが待ち状態に入ると UI がフリーズしてしまいユーザビリティーの観点から好ましくありません。その場合 try lock のような仕組みを利用して確実に lock が取得できる場合のみ lock 取得処理を行う(そうでない場合はイベントループを回し、lock が取得できるようになるまで待つ)と言うことが良く行われます.

上記がここで取り上げた例の擬似コードになります.  パターンの適用例としてはあまり紹介されていないように思いますが、これも一種の Balking パターンだと思います.

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

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

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

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

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

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

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

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

意思決定者がこれらの責任を全面的に取ってくれれば良いのですが、残念ながらここで生じた歪は現場に降りてくるんですよねー。何故なら責任転嫁以前に自分がこのような性質にモロに流されていると言うことを彼もしくは彼女自身が認識出来ていないので、自分に非があると全く思っていないから… その挙句の、激務、長時間労働、デスマーチと言うのはもう鉄板と言っても良いぐらいお決まりな流れな気がします。

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

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

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 処理を書く事ができ、例えば

のようになります。

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