Невозможно получить мьютекс, удерживаемый ожиданием ACE_Condition - PullRequest
1 голос
/ 17 января 2012

У меня есть следующий код, который используется для Push и Pend из очереди. Код вызывающей стороны имеет несколько объектов MsgQ. Возможно, что функции Push и Pend ожидают условного ожидания _notFull->wait() и _notEmpty->wait(). Эти ожидания защищены мьютексом _mut. Ожидания notFull и notEmpty работают с переменными empty и full.

Когда вызывается деструктор, _deleteQueue вызывается изнутри, из чего я хотел бы дать сигнал ожидающим потокам для очистки и прекращения ожидания прихода сигнала. Как только это будет сделано, я удаляю свои объекты. Однако в функции _deleteQueue, когда я пытаюсь выполнить _mut->acquire(), я не могу получить мьютекс. Даже если я игнорирую получение, я не могу broadcast к этим ожидающим потокам. Куда я иду не так?

Спасибо, Викрам.

    MsgQ::~MsgQ()
{
    _deleteQueue();

    delete _mut;_mut=NULL;
    delete  _notFull;_notFull=NULL;
    delete _notEmpty;_notEmpty=NULL;
    delete _PostMutex; _PostMutex = NULL;
    delete _PendMutex; _PendMutex = NULL;
    delete _PostInProgressMutex; _PostInProgressMutex = NULL;
    delete _PendInProgressMutex; _PendInProgressMutex = NULL;
    delete _DisconnectMutex; _DisconnectMutex = NULL;
    free( _ptrQueue ); _ptrQueue = NULL;
}

int MsgQ::Post(Message* msg)
{
    _PostMutex->acquire();
    _postInProgress++;
    _PostMutex->release();

    if (msg)
    msg->print();

    _mut->acquire();
    while (full) 
    {
    _notFull->wait();
    }

    if (!_disconnectInProgress)
    _queuePush(msg);
    _mut->release();

    _PostMutex->acquire();
    _postInProgress--;
    if (_postInProgress==0) 
    {
    _PostInProgressMutex->signal();
    }
    _PostMutex->release();

    return _notEmpty->signal();
}

int MsgQ::Pend(Message*& msg)
{

    _PendMutex->acquire();
    _pendInProgress++;
    _PendMutex->release();

    _mut->acquire();
    while (empty) 
    _notEmpty->wait();

    if (!_disconnectInProgress)
    {
    _queuePop(msg);
    }
    _mut->release();

    _PendMutex->acquire();
    _pendInProgress--;
    if (_pendInProgress == 0)
    {
    _PendInProgressMutex->signal();
    }
    _PendMutex->release();

    return _notFull->signal();
}

void MsgQ::_deleteQueue ()
{
    _PostMutex->acquire();
    if (_postInProgress != 0)
    {
    _PostMutex->release();
    TRACE("Acquiring Mutex.");
    _mut->acquire();
    full = 0;
    _notFull->broadcast();
    _mut->release();
    _PostInProgressMutex->wait();
    }
    else
    {
    _PostMutex->release();
    }

    _PendMutex->acquire();
    if (_pendInProgress != 0)
    {
    _PendMutex->release();
    TRACE("Acquiring Mutex.");
    _mut->acquire();
    empty = 0;
    _notEmpty->broadcast();
    _mut->release();
    _PendInProgressMutex->wait();
    }
    else
    {
    _PendMutex->release();
    }
}

void MsgQ::_initQueue()
{
    _ptrQueue = (Message **)(malloc (size * sizeof (Message*)));

    if (_ptrQueue == NULL)
    {
    cout << "queue could not be created!" << endl;
    }
    else
    {
    for (int i = 0; i < size; i++)
        *(_ptrQueue + i) = NULL;
    empty = 1;
    full = 0;
    head = 0;
    tail = 0;

        try{
        _mut = new ACE_Mutex() ;
        _notFull = new ACE_Condition<ACE_Mutex>(*_mut);
        _notEmpty = new ACE_Condition<ACE_Mutex>(*_mut); 

    _PostMutex = new ACE_Mutex();
    _PendMutex = new ACE_Mutex();
    _PostInProgressMutex = new ACE_Condition<ACE_Mutex>(*_PostMutex);
    _PendInProgressMutex = new ACE_Condition<ACE_Mutex>(*_PendMutex);
    _DisconnectMutex = new ACE_Mutex();

    _postInProgress = 0;
    _pendInProgress = 0;
    _disconnectInProgress = false;

        }catch(...){
            cout << "you should not be here" <<  endl;
        }
    }
}

1 Ответ

0 голосов
/ 18 января 2012

Кажется, что с кодом много проблем, поэтому я бы предложил переработать его:

  1. У вас есть потенциальная возможность тупика, потому что вы получаете _mut перед тем, как перейти в состояние ожидания в обоих случаях.Post и Pend функции.
  2. Вместо использования acquire и release на ACE_Mutex Я бы предложил рассмотреть использование ACE_Guard класса, который может acquire мьютекс при создании и освобожденииэто когда уничтожено.
  3. Почему бы не использовать ACE_Message_Queue вместо создания своего собственного?
...