线程体系结构问题C ++消息传递

时间:2010-07-26 21:22:12

标签: c++ multithreading architecture

简单的问题,我想。

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

处理此问题的最佳方法是什么?现在我有一些代码只是在回调测试中循环,以查看安全服务器是否已发送回复,当它进入时我读取它并返回相应的布尔值。这看起来有点粗糙。

TIA

3 个答案:

答案 0 :(得分:1)

首先,您需要一个包含监视器类的锁定库,该监视器类能够:

  • 获得锁定,保证互斥,即任何时候只有一个线程可以持有锁
  • 睡在锁上,这意味着暂时释放锁,然后睡觉直到可以重新获取锁
  • 锁定信号,通知睡眠线程他们应该唤醒并重新获取锁定。只能在握住锁的同时发出锁定信号。这意味着信号永远不会立即唤醒其他线程。通常,信令线程将发出信号,然后立即释放锁定,允许刚刚发出信号的线程唤醒。在重新启动锁定时,唤醒会产生阻塞调用返回睡眠的效果。

因此,使用某些库提供的功能,您需要实现使用异步安全服务器实现同步服务的安全服务器代理。当在某个线程(表示为线程1)中调用同步authenticate()函数时,应该会发生这种情况:

  1. 代理获取锁
  2. 代理向安全服务器发送请求消息
  3. 代理进入休眠状态,等待结果,线程1现在被阻止并且锁定可用
  4. 安全服务器计算结果
  5. 安全服务器将包含结果的消息发送给代理
  6. 代理消息处理函数在线程2中调用,线程1仍然被阻止
  7. 代理获取线程2中的锁定
  8. 代理从消息中检索结果并将其存储在成员变量
  9. 代理在锁上发出信号,导致线程1在睡眠时阻塞以尝试唤醒,但它不能,因为线程2仍然保持锁定(在sleep()函数内,线程2现在被阻止在获得锁定的电话上)
  10. 代理消息处理程序释放其锁定
  11. 线程1中的睡眠调用重新获取锁定并返回
  12. 线程1中的同步函数然后立即释放其锁并返回结果
  13. 线程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()调用。

答案 1 :(得分:0)

据推测,您可以阻止对安全服务器的异步调用,以有效地使其同步。

答案 2 :(得分:0)

在启动登录检查的函数中,在发送消息后请求检查块。 Windows事件可以使用,布尔标志和boost::condition_variableboost::unique_future也可以。

在从安全服务器接收响应消息的代码中设置事件或future或flag / condition变量。然后,它将唤醒初始函数并允许它将相应的响应返回给初始调用者。