2

UDP 経由で特定のボックスと通信する必要があるプロジェクトに取り組んでいます。システムに接続されているボックスは常に 1 つだけです。接続は、プログラムの全期間続く必要があります。

ハードウェアに必要なデータを提供する際に機能するクラスを作成しました (イェーイ!)。しかし、私の主な問題は、誰か (私の非常にきちんとしたコメントをすべて無視する可能性が高い将来のプログラマー ;)) がこのクラスの複数のインスタンスを作成する可能性があるという事実を説明しなければならないことです。これにより、問題のハードウェアがなぜ同じマシンの 2 つのソケットからデータを受信して​​いるのか疑問に思う、陽気で面白いクラッシュが発生する可能性が高くなります。さらに厄介なのは、オブジェクトを作成すると、定期的に更新を送信するスレッドが実際に生成されることです。したがって、想像上の未来のプログラマーがこれらのオブジェクトのリンク リストを作成するようなことを行った場合 (結局のところ、これは C++ であり、そのようなことを実行する機能があります)、しばらくすると CPU があまり満足しない可能性があることを想像できます。

その結果、私はあなたに目を向けます... 過去にそのような問題を見た SO のより経験豊富な人々。このすべてを処理するシングルトンを作成することについて議論しましたが、私の読書のいくつかは、これが進むべき道ではないかもしれないと信じるように導きました. 彼らに関する情報はインターネット上に山ほどあり、私が見た回答に基づいて非常にデリケートな政治的質問をしているようなものです.

可能な限り多くのコードを保持する私が開発した代替手段は、ハードウェアにデータを渡すアクティブなスレッドがあるかどうかを追跡するために static bool を使用することです。ただし、競合するスレッドが同時にクラスにアクセスしようとしている場合、私のアプローチは競合状態につながる可能性があると思います。ここに私がこれまで持っているものがあります:

// in MyClass.cpp:
static bool running_ = false;  // declared in the class in the .h, but defined here
MyClass::MyClass() {
  // various initialization stuff you don't care about goes here
  if (pthread_create(mythread_, NULL, MyThreadFunc, this) != 0) {
    // error
  }
  else {
    // no error
  }
}

static void* MyClass::MyThreadFunc(void* args) {
  MyClass myclass = static_cast<MyClass>(args);
  // now I have access to all the stuff in MyClass
  // do various checks here to make sure I can talk to the box
  if (!running_) {
    running_ = true;
    // open a connection
    while (!terminate) {  // terminate is a flag set to true in the destructor
      // update the hardware via UDP
    }
    // close the socket
    running_ = false;
  }
}

これにより、アクティブなインスタンスが 1 つだけチェックされることは確かですが、2 つの同時スレッドが !running_ チェックに同時にアクセスし、両方が接続を開く可能性はまだあります。

その結果、ここに私のオプションは何があるのだろうか?シングルトンを実装しますか? 静的変数を機能させる方法はありますか? または、この問題についてコメントし、次のプログラマーがハードウェアと通信するために 2 つのインスタンスを開かないことを理解してくれることを願っていますか?

いつものように、助けてくれてありがとう!

追加するために編集:

別のアイデアが頭に浮かびました...代わりに静的ブールが静的ロックだったらどうでしょうか? そうすれば、ロックを設定してから、後続のインスタンスがロックを取得しようとし、失敗した場合はゾンビ クラスを返すことができます...ちょっと考えてみて...

4

3 に答える 3

0

まず、この想像上の将来の開発者があなたのコードを壊すことに夢中になっている場合、その開発者から何かを守ることはできないと思います。コメント/ドキュメントでうまくいくはずです。彼がそれらを見逃すと、ハードウェア (またはコード) がクラッシュする可能性が高く、彼は気付くでしょう。さらに、彼があなたのクラスを再利用する正当な理由である場合 (同じ種類の他のハードウェアに接続するなど)、厄介な隠されたトリックで彼をブロックしたくありません。

これは、あなたの例では、atomic<bool>同時実行の問題を回避するためにを使用することを検討し、代わりにcompare_exchangeメンバー関数を使用することを検討しif(!running) running = trueます。

static std::atomic<bool> running;
...
bool expected = false;
if(running.compare_exchange_strong(expected, true)) {
    ...
于 2013-06-26T09:39:33.207 に答える
0

ハードウェア自体のインスタンスが 2 つある場合はどうなるでしょうか。[あなたが1つだけだと言っているのは知っていますが、私はそこにいて、「1つしかない!! ああ、<swearword>、今は2つ使う必要があります...」という側面でそれをしました. ]。

もちろん、あなたif(running_)は競合状態です。一度に 2 つのクラスの開始を試行しないように、ある種のアトミック型を実際に使用する必要があります。また、誰かがプログラム全体の 2 つのインスタンスを開始しようとするのを止めることはできません。

ゾンビ クラスを返すことは、悪い解決策のように思えます。例外をスローしたり、エラー値を返したりする方がはるかに良い選択です。

「反対側」に接続数を制御させることは可能でしょうか? つまり、2 番目のインスタンスが通信を試みると、ハードウェアからエラーが返され、"申し訳ありませんが、既に接続されています" というメッセージが表示されます。

これが本当に「答え」ではない場合は申し訳ありません。

于 2013-06-26T09:27:48.473 に答える