ソースを照会する操作がブロックされていない限り(またはそれらがたくさんある場合を除いて)、これにスレッドを使用する必要はありません。Producer
同期または非同期(スレッド)ディスパッチのいずれかで機能するから始めることができます。
template <typename OutputType>
class Producer
{
std::list<OutputType> output;
protected:
int poll_interval; // seconds? milliseconds?
virtual OutputType query() = 0;
public:
virtual ~Producer();
int next_poll_interval() const { return poll_interval; }
void poll() { output.push_back(this->query()); }
std::size_t size() { return output.size(); }
// whatever accessors you need for the queue here:
// pop_front, swap entire list, etc.
};
これで、これから派生して、各サブタイプProducer
にメソッドを実装できます。query
コンストラクターで設定poll_interval
してそのままにするか、を呼び出すたびに変更することができquery
ます。ディスパッチメカニズムに依存しない、一般的なプロデューサーコンポーネントがあります。
template <typename OutputType>
class ThreadDispatcher
{
Producer<OutputType> *producer;
bool shutdown;
std::thread thread;
static void loop(ThreadDispatcher *self)
{
Producer<OutputType> *producer = self->producer;
while (!self->shutdown)
{
producer->poll();
// some mechanism to pass the produced values back to the owner
auto delay = // assume millis for sake of argument
std::chrono::milliseconds(producer->next_poll_interval());
std::this_thread::sleep_for(delay);
}
}
public:
explicit ThreadDispatcher(Producer<OutputType> *p)
: producer(p), shutdown(false), thread(loop, this)
{
}
~ThreadDispatcher()
{
shutdown = true;
thread.join();
}
// again, the accessors you need for reading produced values go here
// Producer::output isn't synchronised, so you can't expose it directly
// to the calling thread
};
これは、プロデューサーをスレッドで実行し、頻繁に要求された場合にポーリングする単純なディスパッチャーの簡単なスケッチです。生成された値を所有者に戻すことは表示されないことに注意してください。これは、それらにアクセスする方法がわからないためです。
また、シャットダウンフラグへのアクセスを同期していないことにも注意してください。おそらくアトミックであるはずですが、生成された値を使用して行うことを選択すると、暗黙的に同期される可能性があります。
この組織では、たとえばselect / pollループから、またはBoost.Asioやプロデューサーごとの期限タイマーなどを使用して、単一のスレッドで複数のプロデューサーにクエリを実行する同期ディスパッチャーを簡単に作成できます。