2011-11-14 28 views
2

我在我的应用程序中使用boost库进行线程和同步。跨线程的C++同步和异常处理

首先我必须说线程内的异常对于同步来说是compilitey新事物对我来说。 在下面的任何情况下,我想要实现的伪代码。我想要同步的线程抛出异常,可能从执行notify的线程中抛出异常。我怎样才能做到这一点?

无法找到有关的异常使用boost线程模型

非常感谢事先与横纱的互动扔从堆栈溢出的任何话题!

// mutex and scondition variable for the problem 
mutable boost::mutex conditionMutex; 
mutable boost::condition_variable condition; 

inline void doTheThing() const { 

    if (noone doing the thing) { 
     try { 
      doIt() 
      // I succeeded 
      failed = false; 
      condition.notify_all(); 
     } 
     catch (...) { 
      // I failed to do it 
      failed = true; 
      condition.notify_all(); 
      throw 
     } 
    else { 
     boost::mutex::scoped_lock lock(conditionMutex); 
     condition.wait(lock); 
     if (failed) { 
      // throw the same exception that was thrown from 
      // thread doing notify_all 
     } 
    } 

}

回答

1

所以,你想击中doTheThing()第一个线程调用doIt(),并击中doTheThing()所有后续线程等待第一个线程完成调用doIt()他们再继续。

我想这应该做的伎俩:

boost::mutex conditionMutex; // mutable qualifier not needed 
bool failed = false; 
bool done = false; 

inline void doTheThing() const { 

    boost::unique_lock uql(conditionMutex); 

    if (!done) { 
     done = true; 
     try { 
      doIt(); 
      failed = false; 
     } 
     catch (...) { 
      failed = true; 
      throw 
     } 
    } 
    else if (failed) 
    { 
     uql.unlock(); 
     // now this thread knows that another thread called doIt() and an exception 
     // was thrown in that thread. 
    } 

} 

重要提示:

调用doTheThing()必须采取锁定每个线程。这是没有办法的。您正在同步线程,并且为了让线程知道另一线程中发生的事情,它必须锁定。 (或者它可以使用原子内存操作,但这是一种更先进的技术。)变量faileddoneconditionMutex保护。

当函数通过抛出异常正常退出时,C++将调用uql的析构函数。

编辑呵呵,至于抛出所有其他线程的异常,忘了这一点,这几乎是不可能的,这不是在C++中的事情。相反,每个线程都可以检查第一个线程是否在我上面指出的地方成功调用doIt()

编辑对于将异常传播到另一个线程没有语言支持。您可以将传播异常的问题推广到另一个线程,将消息传递到另一个线程。线程之间传递消息的问题有很多库解决方案(boost::asio::io_service::post()),您可以传递包含异常的消息,并在接收到消息时引发异常。不过,这是一个糟糕的主意。只有在发生错误时才会抛出异常,从而阻止您通过普通函数返回来解除调用堆栈。这就是一个例外 - 在返回通常方式时从函数返回的另一种方式没有任何意义。

+0

感谢您的回答。我知道我需要锁定if语句让别人通过。我刚刚从伪代码中退出了锁定。您的解决方案要求每个线程都需要通过doIt()。我想阻塞的线程等待工作线程完成它正在做的事情。实际的问题是如何将可能的异常传播给同步的线程。那么你是否说这完全不可能? – Lauri

+0

@Lauri 1 of 2:仔细看看,只有第一个线程通过'doIt()',其余的线程在检查完成后会跳过'doIt()'。 –

+0

@Lauri 2 of 2:我澄清了我的答案,参见上文。 –