我目前在以下设置中使用void Futures进行线程同步:线程A将线程B提交到消息线程队列以产生线程A所需的资源。线程A等待该资源,但如果占用过多资源则将放弃。时间长,然后将继续进行而没有资源将提供的功能。
对于期货,对线程B的调用如下所示(以伪代码:]
/* Thread B function signature: void ThreadB(std::promise<void> p); */
std::promise<void> promised_resource;
std::future<void> future_resource {promised_resource.get_future()};
SubmitToMessageThread([p = std::move(promised_resource)]() mutable { ThreadB(std::move(p)); }));
if (future_resource.wait_for(std::chrono::seconds(1)) == std::future_status_ready)
/* work with resource if thread B has called p.set_value() to indicate the resource is ready */;
else
/* make do without the resource */
消息线程比线程A持续更长的时间,但是线程B [[0]移动了 promise
,因此线程B完全控制了Promise的生存期,并且在访问之后不应该有访问promise
的风险。即使线程B在线程A完成之后正在运行,它也会被销毁。 promise
和future
之间的分割允许每个线程控制它负责的对象的生存期。
semaphore
)。最初,我将为线程B提供对semaphore
的引用。如果可以保证线程B不会超过线程A,那将起作用。但是在我的设置中,情况并非如此。这是否意味着除了shared_ptr
之外,我还必须使用semaphore
(或其他类似机制)?semaphore
。如果可以保证引用在线程B的生命周期内仍然有效,那将是可行的,但在所描述的情况下情况并非如此。/* Thread B function signature: void ThreadB(std::shared_ptr<std::binary_semaphore>& done); */
auto done {std::make_shared<std::binary_semphore>(0)};
SubmitToMessageThread([&done]() { ThreadB(done); }));
if (done.wait_for(std::chrono::seconds(1)))
/* work with resource if thread B has called done->release() to indicate the resource is ready*/
else
/* make do without the resource */
但是线程B没有这样的终身保证。线程A的wait_for
可能在线程B完成之前到期,线程A可能继续完成,导致semaphore
销毁,然后线程B使用。我们必须管理生存期,通常使用shared_ptr
。如以下:
/* Thread B function signature: void ThreadB(std::shared_ptr<std::binary_semaphore> done); */
auto done {std::make_shared<std::binary_semphore>(0)};
SubmitToMessageThread([done]() { ThreadB(done); }));
if (done.wait_for(std::chrono::seconds(1)))
/* work with resource if thread B has called done->release() to indicate the resource is ready*/
else
/* make do without the resource */
总而言之,除非仔细管理生命周期,否则信号量会提供另一个步枪机会。