Exemple #1
0
std::auto_ptr<ArgumentDecoder> Connection::waitForMessage(MessageID messageID, uint64_t destinationID, double timeout)
{
    // First, check if this message is already in the incoming messages queue.
    {
        MutexLocker locker(m_incomingMessagesLock);

        for (size_t i = 0; i < m_incomingMessages.size(); ++i) {
            const IncomingMessage& message = m_incomingMessages[i];

            if (equalIgnoringFlags(message.messageID(), messageID) && message.arguments()->destinationID() == destinationID) {
                std::auto_ptr<ArgumentDecoder> arguments(message.arguments());
                
                // Erase the incoming message.
                m_incomingMessages.remove(i);
                return arguments;
            }
        }
    }
    
    double absoluteTime = currentTime() + timeout;
    
    std::pair<unsigned, uint64_t> messageAndDestination(std::make_pair(messageID.toInt(), destinationID));
    
    {
        MutexLocker locker(m_waitForMessageMutex);

        // We don't support having multiple clients wait for the same message.
        ASSERT(!m_waitForMessageMap.contains(messageAndDestination));
    
        // Insert our pending wait.
        m_waitForMessageMap.set(messageAndDestination, 0);
    }
    
    bool timedOut = false;
    
    // Now wait for it to be set.
    while (!timedOut) {
        MutexLocker locker(m_waitForMessageMutex);

        HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*>::iterator it = m_waitForMessageMap.find(messageAndDestination);
        if (it->second) {
            std::auto_ptr<ArgumentDecoder> arguments(it->second);
            m_waitForMessageMap.remove(it);
            
            return arguments;
        }
        
        // We didn't find it, keep waiting.
        timedOut = !m_waitForMessageCondition.timedWait(m_waitForMessageMutex, absoluteTime);
    }

    // We timed out, now remove the pending wait.
    {
        MutexLocker locker(m_waitForMessageMutex);
        m_waitForMessageMap.remove(messageAndDestination);
    }
    
    return std::auto_ptr<ArgumentDecoder>();
}
Exemple #2
0
std::unique_ptr<MessageDecoder> Connection::waitForMessage(StringReference messageReceiverName, StringReference messageName, uint64_t destinationID, std::chrono::milliseconds timeout)
{
    // First, check if this message is already in the incoming messages queue.
    {
        MutexLocker locker(m_incomingMessagesLock);

        for (auto it = m_incomingMessages.begin(), end = m_incomingMessages.end(); it != end; ++it) {
            std::unique_ptr<MessageDecoder>& message = *it;

            if (message->messageReceiverName() == messageReceiverName && message->messageName() == messageName && message->destinationID() == destinationID) {
                std::unique_ptr<MessageDecoder> returnedMessage = std::move(message);

                m_incomingMessages.remove(it);
                return returnedMessage;
            }
        }
    }

    std::pair<std::pair<StringReference, StringReference>, uint64_t> messageAndDestination(std::make_pair(std::make_pair(messageReceiverName, messageName), destinationID));
    
    {
        std::lock_guard<std::mutex> lock(m_waitForMessageMutex);

        // We don't support having multiple clients wait for the same message.
        ASSERT(!m_waitForMessageMap.contains(messageAndDestination));
    
        // Insert our pending wait.
        m_waitForMessageMap.set(messageAndDestination, nullptr);
    }
    
    // Now wait for it to be set.
    while (true) {
        std::unique_lock<std::mutex> lock(m_waitForMessageMutex);

        auto it = m_waitForMessageMap.find(messageAndDestination);
        if (it->value) {
            std::unique_ptr<MessageDecoder> decoder = std::move(it->value);
            m_waitForMessageMap.remove(it);

            return decoder;
        }

        // Now we wait.
        if (m_waitForMessageCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
            // We timed out, now remove the pending wait.
            m_waitForMessageMap.remove(messageAndDestination);

            break;
        }
    }

    return nullptr;
}