私は主に .NET でプログラミングしており、Tasks、ResetEvents などの非同期/同時実行プリミティブが大好きです。今日、初めて C++ プログラムに意味のある変更を加え、ビルド プロセス全体がどのように機能するかを理解しました ( LigthningDB.NET プロジェクトを更新しました)。 0.9.14 に)。しかし、私はまだ C++ の知識が不足しています。
LMDB プロジェクトに (自分のニーズのために) 追加したい新機能の 1 つは、通知システム (Redis に似ています) です。
- テーブル内のすべてのデータ変更を通知する待機可能なオブジェクトを返すカーソルが必要です。
- キーまたはキー + 値など、シグナル (データ構造へのポインター) と一緒にデータを取得したい。
- このオブジェクトはカーソルと共に破棄され、カーソルの一部ですが、カーソルが参照を持つ DB の変更を通知します。
- これは、いつの日か (または何年か) クロスプラットフォームで動作するはずです。彼らが仕事をするなら、私はどんな汚いWindows固有のハックでもOKです.
典型的なユースケースは、新しいメッセージを待っているライターと N 人のリーダーです。これにより、IPC と高速持続性 2-in-1 が可能になります。LMDB は、異なるプロセスからの同時読み取りをサポートしています (Esent と LevelDB はサポートしていません)。
System.Threading
プリミティブは C++ から利用でき、ブロッキング呼び出しに WaitHandle を使用する方法を理解しています。これを非同期にする方法はありますか? 非同期同期プリミティブに関する優れた一連の記事がありますが、それらはTaskCompletionSource
.NET 内でのみ機能する and を使用します。ネイティブ相互運用のために同様のソリューションを作成することは可能ですか?
解決策の 1 つは、変更を 1 つのリスナー/ディスパッチャー (Redis またはRhino.Queuesスタイル) に変換する名前付きパイプまたはソケットである可能性がありますが、パフォーマンスが低下します。すでにメモリ内にあるデータ構造へのポインタ。
もう 1 つのオプションは、リスニング カーソルをキーに移動し、信号を送信することです。信号の後、C# リスナーは、カーソルが更新されたキーに値を持っていることを認識します。この種類はデータ転送部分を解決しますが、WaitHandles を使用するとブロックされます。私の使用例では、ブロックはソケット [割り当て/コピー/遅延] の組み合わせよりも悪いです。
より良いオプションはありますか?
追加の質問:
- ここで自転車を再発明していますか?
- .NET プログラムが C/C++ シグナル (存在する場合) を待機する (ノンブロッキング) オープン ソース ライブラリを教えてください。
- そのワークフローに LMDB を使用する必要がありますか? 私の優先順位は Windows で、LevelDB をまったく機能させようとして非常に苦労しました (試行をやめました)。LMDB が行うすべてのこと + シグナリングのためのより良い代替手段はありますか?
アップデート
ドキュメントでこの方法を見つけました:
public static Task WaitOneAsync(this WaitHandle waitHandle)
{
if (waitHandle == null) throw new ArgumentNullException("waitHandle");
var tcs = new TaskCompletionSource<bool>();
var rwh = ThreadPool.RegisterWaitForSingleObject(waitHandle,
delegate { tcs.TrySetResult(true); }, null, -1, true);
var t = tcs.Task;
t.ContinueWith(_ => rwh.Unregister(null));
return t;
}
のドキュメントは次のようにThreadPool.RegisterWaitForSingleObject
述べています。
待機操作は、スレッド プールのスレッドによって実行されます。デリゲートは、オブジェクトの状態がシグナル状態になるか、タイムアウト間隔が経過すると、ワーカースレッドによって実行されます。...待機スレッドは、Win32 WaitForMultipleObjects関数を使用して、登録された待機操作を監視します。
これらは 2 つの異なるスレッドであり、シグナルがない場合にブロックされるのは最初の待機スレッドだけであるというのは正しいですか?