在我的代码中,我有一个使用静态随机引擎生成器运行的函数,如果用户尝试从与主线程不同的线程调用此函数,我希望能够抛出错误。
例如,如果您考虑以下功能:
void f()
{
if (/* SOMETHING */) {
throw std::future_error("ERROR = f() : cannot be executed in parallel");
}
}
会是/* SOMETHING */
什么?
在我的代码中,我有一个使用静态随机引擎生成器运行的函数,如果用户尝试从与主线程不同的线程调用此函数,我希望能够抛出错误。
例如,如果您考虑以下功能:
void f()
{
if (/* SOMETHING */) {
throw std::future_error("ERROR = f() : cannot be executed in parallel");
}
}
会是/* SOMETHING */
什么?
我在线程方面不是很有经验,但不知何故我很想按照单例/其他设计模式做一些事情。
话虽这么说,我不相信这个想法很优雅,我不知道你为什么要这样做,所以我不知道如何提出任何替代方案......
虽然我确实认为可以在 main 中创建一个单例,这样就可以防止任何从其他线程调用 f 的尝试。
单身人士通常被滥用,所以......我会小心的。
尽管我认为您要实现的目标不是很优雅(锁定或保存每个线程的随机引擎生成器的状态,例如使用线程本地存储可能会更好),但这里有一个解决您所要求的解决方案:
static const auto mainThreadId = std::this_thread::get_id();
void f()
{
if (std::this_thread::get_id() != mainThreadId) {
throw std::future_error("ERROR = f() : cannot be executed in parallel"
"/from a thread other than the main one");
}
}
一个非常非常好的解决方案是让您检索随机数是线程安全的。
这可以通过以下两种方式之一完成:
让我们谈谈#1。由于您建议包装调用以获取随机数,因此使用 mutex 包装这些调用并不太牵强。我们不是简单地在运行时将问题呈现给用户(这通常是一个非常糟糕的开发选择),而是解决了这个问题。唯一的缺点是我们减慢了对随机数生成器的调用速度——这可能是可以接受的,但如果不是……请选择选项#2。
而且,对于#2 ...您说这是一个静态随机数生成器。也许这意味着您不能再制作它的副本,但这无论如何都值得一提。rand
并且srand
是这样的。但是,如果您使用的是 C++11 之类的东西std::uniform_int_distribution
,那么为每个线程创建一个副本应该没有问题。(也许考虑std::thread_local
一下你是否找不到放置每个线程副本的好地方。)