2

一連のネットワーク接続にデータを送信する C++ のマルチスレッド プロジェクトに取り組んでいます。何が起こっているかを示す擬似コードを次に示します。

class NetworkManager
{
    Thread    writer;      // responsible for writing data in queues to the network
    Queue[]   outqueue;    // holds data until the network is ready to receive it
    Network[] nets;        // sockets or whatever
    Mutex[]   outlock;     // protects access to members of outqueue
    Mutex     managerlock; // protects access to all queues
    Condition notifier;    // blocks the write thread when there is no data
}

実際にはそれよりもはるかに複雑ですが、多くの不要な詳細を削除しました。重要な詳細の 1 つは、ネットワークがレート制限されていることと、プログラムがデータを送信するのとは別にキューに入れる機能が設計の特徴であることです (プログラムはネットワーク書き込みでブロックされているため、新しいデータの処理を待つ必要はありません)。 )。

以下は、プログラムがこのクラスとどのように対話することが期待されるかについての簡単な説明です。QueueWriteToNetworkDoAdministrativeStuffは、私の実装では、同じ外部スレッドによって管理されていることに注意してください。

QueueWriteToNetwork(network, data) // responsibility of external thread
    Let i = the index of the network to send to
    Lock(outlock[i])
    outqueue[i].Add(data)
    Unlock(outlock[i])
    Signal(notifier)

DoAdministrativeStuff(network, more) // responsibility of external thread
    Lock(managerlock)
    more.Process() // might do any of the following:
                   // connect or disconnect networks
                   // add or remove networks from list
                   // immediate write data to network, bypassing rate limiting
                   // other things that I forgot
    Unlock(managerlock)

WriterThreadMain() // responsibility of internal write thread
    Lock(managerlock)
    Loop forever:
        Check for data in every queue (locking and unlocking each queue)
        If all queues have no data to write:
            Wait(notifier, managerlock)
            continue
        If outqueue[i] has data ready to write
            Lock(outlock[i])
            Send data from outqueue[i]
            outqueue[i].Pop()
            Unlock(outqueue[i])

ご覧のとおり、このアプローチにはいくつかの問題があります (たとえば、キュ​​ーが空かどうかをチェックしながら書き込みがネットワークにキューに入れられているQueueWriteToNetwork場合WriterThreadMain、への呼び出しSignal(notifier)がドロップされる可能性があり、書き込みキューデータの準備ができていても、待機し続ける可能性があります)。

次のことが可能になるように、これを表現する必要があります。

  • 書き込みキューへのデータの追加はブロックされないか、かなり短い時間だけブロックされます (具体的には、進行中のネットワーク書き込みの間はブロックされません)。
  • DoAdministrativeStuff関数には、ライター スレッドが安全な状態でブロックされている (つまり、キュー、キュー ロック、またはネットワークにアクセスしていない) ことを保証する機能が必要です。

セマフォを使用して、書き込みキュー内の項目数を追跡する可能性を探りました。これにより、前述の更新の紛失の問題が解決されます。

最後に、私は Linux をターゲットにしています (Posix ライブラリを使用してpthread_tpthread_mutex_tpthread_cond_t、およびの型を提供しますsem_t)。Windows との互換性は気にしません。また、Boost はお勧めしません。Boost ヘッダーをコードに取り込むと、コンパイルに耐えられないほど時間がかかります。

4

0 に答える 0