0

As the current post title saying about it, the boost boost::interprocess::interprocess_condition::wait is suppose to atomically unlock mutex while it waits, but it doesn't.

In the following code:

boost::interprocess::scoped_lock< boost::interprocess::interprocess_mutex > state_access_lock(impl->state->state_access_mut);
impl->state->state_access_cond.wait(state_access_lock);

In VS2010 into debugging mode i pressed pause and was surprised when i saw that state_access_lock is still locked while waiting.

But that's not what boost's doc is saying here.

Does anybody have a suggestion?

Thanks.

4

2 回答 2

0

根据目前的评论,我想我可以推断出答案。

不要相信传递给 interprocess_condition::wait() 的 scoped_lock 的成员。interprocess_condition 的合同(与 interprocess_condition_any 不同)规定您只能将其与 interprocess_mutex 的锁一起使用。知道了这一点,条件变量将内部互斥锁从您的锁中拉出,以比它对锁一无所知时更有效地完成其工作。

因此,在解锁互斥锁时,它不会在您的 scoped_lock 上调用 unlock(),而是直接在互斥锁上调用。这对于内部实现来说很好;不要在家里这样做。如果在锁超出范围之前不重新锁定互斥锁,就会发生不好的事情。

换句话说,您在调试器中看到的行为并不表示存在问题。如果你有一个死锁,它必须在其他地方。

编辑

给出的实际代码中的条件变量对我来说看起来不错。我发现与 start_mut 的交互有点奇怪。你确定那部分没有问题吗?

于 2013-06-14T09:51:04.693 回答
0

Ok this is the first thread:

void CSharedMemory::start(start_mode mode)
{
bool start_mut_locked = true;
impl->running = true;
impl->mode = mode;

stateMetaStruct* state = impl->proc_state;

boost::interprocess::scoped_lock< boost::interprocess::interprocess_mutex > state_access_lock(state->state_access_mut);

while(impl->running)
{
    state->data_written = false;
    while(!state->data_written)
    {
        if(start_mut_locked)
        {
            // We can now unlock and let other threads to send data.
            impl->start_mut.unlock();
            start_mut_locked = false;
        }

        state->state_access_cond.wait(state_access_lock); // wait here upon sharedmemory's state change
        boost::interprocess::offset_ptr< stateMetaStruct > s = impl->shm_obj.find< stateMetaStruct >(boost::interprocess::unique_instance).first;
        state = s.get();

        if(!state->data_written)
        {
            // Spurious wakeup.
            glm_debug("Spurious wakeup.");
        }

        if(this == state->data_written_by_proccess)
        {
            state->data_written = false;
            glm_debug("Ignoring my proper event.");
        }
    }

    if(impl->running)
    {
        // Got action from other process.
        const interprocess_actions state_action = state->action;

        if(DO_STOP == state_action) {
        }
        else if(DUMP_USERS_REQUEST == state_action) {
            impl->stateChangedListener->onDumpUsersRequest();
        }
        else if(DUMP_USERS_REPLY == state_action) {
        }
        else {
            glm_err("Unexpected state.");
        }
    }
   }
}

The second thread try to send data using this method:

void CSharedMemory::sendDumpUsersRequest()
{
// Ensure shm is started.
boost::mutex::scoped_lock lk(impl->start_mut);

glm_debug("%s", __FUNCTION__);

boost::interprocess::offset_ptr< stateMetaStruct > s = impl->shm_obj.find< stateMetaStruct >(boost::interprocess::unique_instance).first;
stateMetaStruct* state = s.get();

boost::interprocess::scoped_lock< boost::interprocess::interprocess_mutex > state_access_lock(state->state_access_mut);

state->action = DUMP_USERS_REQUEST;

state->data_written = true;
state->data_written_by_proccess = this;

// Send request.
state->state_access_cond.notify_all();
}

The behavior is, the second thread block when trying to acquire the scoped_mutex because the first one is waiting on it.

于 2013-06-14T15:23:20.083 回答