代码之家  ›  专栏  ›  技术社区  ›  shaz

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

  •  1
  • shaz  · 技术社区  · 15 年前

    我想这是个简单的问题。

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

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

    TIA公司

    3 回复  |  直到 15 年前
        1
  •  1
  •   Rasmus Storjohann    14 年前

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

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

    因此,有了某些库中提供的功能,您需要实现一个安全服务器代理,该代理使用异步安全服务器来实现同步服务。当同步 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() 在监视器上调用。

        2
  •  0
  •   Steven Sudit    15 年前

    想必,您会阻止对安全服务器的异步调用,以有效地使其同步。

        3
  •  0
  •   Anthony Williams    15 年前

    在发起登录检查的函数中,在发送消息以请求对某些内容进行检查块之后。Windows事件将起作用,布尔标志和 boost::condition_variable 或a boost::unique_future

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