2

私のプログラムでは、単一のスレッドプールを使用して、タイマータスク、非ブロッキングソケットI / Oなどのすべてのタスクをディスパッチします。タスクは実際にはコールバック関数であり、特定のイベントを受信したときに実行されます。

アーキテクチャは次のとおりです。

  1. メインスレッドはepoll()を呼び出してI / Oイベントを収集し、I/Oコールバックをスレッドプールにディスパッチします。

  2. メインスレッドはタイマータイムアウトも処理し、タイムアウトコールバックをスレッドプールにディスパッチします

  3. I / Oコールバックでは、I / O処理の結果によっては、1つのタイマータスクがキャンセルされる場合があります。

  4. 1つのI/Oコールバックが実行されている間、対応するソケットはそれ以上の同一のイベントについて監視されません。

  5. 1つのタイマーコールバックが実行されている間、そのタイマータスクはタイマータスクキューから一時的に削除されます。

ここに問題があります:

  1. プール内のスレッドAが、タイマーコールバックTを実行している間。

  2. プール内のスレッドBは別のコールバック(ソケットI / O読み取りイベントに登録)を実行している可能性があります。受信した要求を処理した後、スレッドBはタイマータスクTを削除することを決定しますが、そのタイマータスクTは現在スレッドAによって実行されています。

タイマータスクのロックを追加できますが、どこにロックを配置すればよいですか?タイマータスク構造にロックオブジェクトを配置できません。タスクオブジェクトを解放することを決定したときに、ロックを取得している必要があります。ロックを解放して保持すると、未定義の動作が発生する可能性があります。

pthread_mutex_lock(T->mutex);
 free(T);
 /*without a pthread_mutex_unlock(T->mutex);*/

そして、別のスレッドがブロックされた場合はどうなりますか:

pthread_mutex_lock(T->mutex);

これらの問題に対処しないと、仕事を続けることはできません。助けてください!

単一のプロセスで異なるタイプのタスクに個別のスレッドプールを使用する必要がありますか?または、シングルスレッドを使用しますか?

どんな提案でも大歓迎です!

4

2 に答える 2

0

独自のミューテックスで保護されたタイマーのグローバルテーブルを使用できます。テーブルは実際にはグローバルである必要はありませんが、I/Oを実行しているすべてのものを所有しているものなどのコレクションに属することができます。

次に、次のロジックを使用します。

タイマーを作成するには

  1. グローバルテーブルをロックします。

  2. 状態「保留中」のグローバルテーブルにタイマーを追加します。

  3. グローバルテーブルのロックを解除します。

  4. スレッドプールでタイマーをスケジュールします。

タイマーを起動するには

  1. グローバルテーブルをロックします。

  2. タイマーの状態を確認してください。「保留中」でない場合は、タイマーを削除し、テーブルのロックを解除して停止します。

  3. タイマーの状態を「発砲」に変更します。

  4. グローバルテーブルのロックを解除します。

  5. タイマー動作を行ってください。

  6. グローバルテーブルをロックします。

  7. テーブルからタイマーを削除します。

  8. グローバルテーブルのロックを解除します。

タイマーをキャンセルするには

  1. グローバルテーブルをロックします。

  2. タイマーを見つけます。状態が「保留中」の場合は「キャンセル」に変更してください。削除しないでください。

  3. グローバルテーブルのロックを解除します。

于 2012-09-17T09:48:05.603 に答える
0

参照はタスクを数えることができませんか?プール内のスレッドAがタイマーコールバックTを実行している場合、それをマークします(たとえば、インターロックされたインクリメントを使用します)。終了したら、使用量を減らします。使用量がゼロになるまで解放できません。

于 2012-09-17T10:04:17.043 に答える