boost mutex, условие, scoped_lock, я их здесь не так? - PullRequest
4 голосов
/ 07 мая 2011
class MyClass
{
public:
    void PushMessage(MyMessage m) // Thread 1 calls this
    {
        boost::mutex::scoped_lock lock(mMutex);
        mQueue.push_back(m);
        mCondition.notify_one();
    }

    MyMessage PopMessage()
    {
        boost::mutex::scoped_lock lock(mMutex);
        while(mQueue.empty())
            mCondition.wait(lock);

        MyMessage message = mQueue.front();
        mQueue.pop_front();
        return message;
    }

    void foo() // thread 2 is running this loop, and supposed to get messages
    {
        for(;;)
        {
            MyMessage message = PopMessage();

            do_something(message);
        }
    }
private:
    std::deque<MyMessage> mQueue;

    boost::mutex mMutex;
    boost::condition mCondition;
};

Когда я запускаю код, вызывается PushMessage, и foo() ожидает PopMessage(), но PopMessage никогда не возвращается.

Что тут не имеет значения do_something, я думаю.

Что я здесь не так делаю?Как ни странно, приведенный выше код работал нормально под Mac, но у меня возникли проблемы с Linux.
Надежная версия 1.44.0

Спасибо

Ответы [ 2 ]

1 голос
/ 07 мая 2011

Вместо того, чтобы срок действия объекта блокировки истек до того, как он разблокируется, вы можете попытаться вручную разблокировать мьютекс в PushMessage(), прежде чем разблокировать ожидающий поток, т. Е.

void PushMessage(MyMessage m) // Thread 1 calls this
{
    boost::mutex::scoped_lock lock(mMutex);
    mQueue.push_back(m);

    lock.unlock(); // <== manually unlock

    mCondition.notify_one();
}

Таким образом, когдапоток 2 разблокируется, не будет времени "перехода", когда поток 1 содержит блокировку, а поток 2 пытается получить блокировку вашего мьютекса.Я не понимаю, почему это может создать проблемы, но опять же, по крайней мере, у вас не будет потока 2, пытающегося вызвать lock.lock(), в то время как поток 1 все еще содержит блокировку.

0 голосов
/ 07 мая 2011

Я думаю, вам нужно 2 объекта мьютекса, один для синхронизации вызова метода в разных потоках, другой для ожидания условия. Вы их смешали.

...