2010-07-26 40 views
1

简单的问题,我想。线程体系结构问题C++消息传递

我有一个线程可以响应用户通过TCP连接时调用的回调函数。如果我接受或拒绝登录,该回调需要答案。问题是我必须通过异步消息传递向安全服务器发送登录请求并等待响应。

处理这个问题的最佳方法是什么?现在我有一些代码只是在回调测试中循环来查看安全服务器是否发送了回复,并且当它回来时我读取并返回适当的布尔值。它看起来很粗暴。

TIA

+1

就像我在想也许是一个提升condition_variable或一些这样的事情。 – shaz 2010-07-26 22:16:17

+0

我注意到最近几个几乎相同的问题。这是一个类的项目吗?只是好奇。 – 2010-07-30 12:14:32

回答

0

想必,你会阻止你的异步调用安全服务器来有效地使之同步。

+0

是的,但阻止如何使用互斥锁,睡眠和检查变量?对SecSrv的调用是异步的,所以一旦我打电话,它立即返回,我必须做一些明确的事情来阻止并等待返回消息。我真的很想问一个我认为是什么样的问题,什么是最平滑的方式来编码? – shaz 2010-07-26 21:43:02

+0

我无法阻止异步调用,我稍后发送消息并在不同的线程中接收消息。 – shaz 2010-07-27 17:03:37

+0

我在看这里的示例代码(http://www.windows-tech.info/13/e64a22df23c19164.php),我没有看到任何特殊的原因,为什么你的回调无法阻止手动重置事件之前返回。 – 2010-07-27 18:28:21

0

在启动登录检查的函数中,在发送消息以请求检查块上的内容之后。 Windows事件将起作用,布尔标志和boost::condition_variableboost::unique_future也会起作用。

在接收来自安全服务器的响应消息的代码中设置事件或未来或标志/条件变量。然后这将唤醒初始函数并允许它将适当的响应返回给初始调用者。

1

首先,你需要一个锁定库,包含有能力来监控类:

  • 获得锁,保证互斥,即只有一个线程可以在任何时候
  • 持有锁
  • 睡在锁上,这意味着暂时释放锁,并处于休眠状态,直到可以重新获取锁为止
  • 锁定信号,通知睡眠线程它们应该被唤醒并重新获取锁。只有在持锁的情况下才能在锁上发信号。这意味着信号永远不会唤醒其他线程。通常情况下,信号线程将发出信号,然后立即释放锁,允许刚刚发送信号的线程唤醒。唤醒具有将阻塞呼叫返回到休眠状态的效果,并重新获得了锁定。

因此,从某些库中可用的功能,您需要实现安全服务器代理,该代理使用异步安全服务器来实现同步服务。当同步authenticate()函数被调用一些线程(表示线程1),这是应该发生的事情:

  1. 代理获取锁
  2. 代理将请求消息发送到安全服务器
  3. 代理去睡眠,等待结果,线程1已被锁住和锁可用
  4. 安全服务器计算结果
  5. 安全服务器发送消息以将结果提供给代理
  6. 代理消息处理函数被调用线程2,线程1仍然受阻
  7. 代理获取在螺纹锁2
  8. 代理从消息并将其存储在一个成员变量
  9. 的检索结果代理信号在锁上,导致线程1在睡眠中阻塞以尝试唤醒,但它不能,因为线程2仍然保持锁定(在sleep()函数内,线程2现在在呼叫时被阻塞以获取锁)
  10. 代理消息处理程序释放其锁
  11. 线程1中的睡眠呼叫重新获取锁并返回
  12. 在线程的同步功能1,则立即释放其锁定,并返回结果

与线程1重新获得锁只能立即释放它可能看起来毫无意义的最后一部分,但它很重要,因为这可以确保消息处理程序在同步函数继续之前完成。

伪代码,它实际上看起来很简单,你可能期望:

class SecutityProxy 
{ 
public: 
    SecutityProxy(SecurityServer& server) : m_server(server) 
    {} 
    Result authenticate(username, password) 
    { 
     m_monitor.lock(); 
     m_server.send_message(username, password); 
     m_monitor.sleep(); 
     m_monitor.unlock(); 
     return m_result; 
    } 
    void message_received(message) 
    { 
     m_monitor.lock(); 
     m_result = message; 
     m_monitor->signal(); 
     m_monitor.unlock(); 
    } 
private: 
    SecurityServer& m_server; 
    Monitor m_monitor; 
    Result m_result; 
}; 

注意,此实现不能同时处理多个请求!为了处理多个并发请求,您需要能够存储多个结果。您还需要存储与每个请求对应的线程的线程句柄。在消息处理程序中,您需要确定哪个线程在任何给定的请求上被阻塞,然后在signal()调用中唤醒相关线程,锁定库必须支持该线程。

还请注意,强烈建议实施RAII类来处理监视器上的lock()unlock()调用。