UB ?
От: dcb_BanDos Чехия  
Дата: 06.10.17 17:12
Оценка:
Два потока, один дергает WaitAndPopInfo, второй Push. Может ли компилятор прооптимизировать while( m_queue.empty() ) до while(true/false)?

    typedef boost::condition_variable condition_variable_t;
    typedef boost::shared_ptr<condition_variable_t> condition_variable_ptr_t;

    boost::mutex m_mutex;
    condition_variable_ptr_t m_ptrCondition;
    std::queue< size_t > m_queue;

bool boo::TryPopInfo( size_t& areaId )
{
    boost::mutex::scoped_lock lock( m_mutex );
    if ( m_queue.empty() )
        return false;

    areaId = m_queue.front();
    m_queue.pop();

    return true;
}

bool CAreaIdSink::WaitAndPopInfo( stream_size_t& areaId )
{
    {
        boost::mutex::scoped_lock lock( m_mutex );
        while( m_queue.empty() )
        {
            boost::system_time const timeoutAbsTime = boost::get_system_time() + boost::posix_time::milliseconds( queueConditionTimeout );
            m_ptrCondition->timed_wait( lock, timeoutAbsTime );
        }
    }
    
    return TryPopInfo( areaId );
}


void CAreaIdSink::Push( cnt::byte_array_ptr_t ptrBuf )
{
    cnt::CBufReader reader( ptrBuf );
    boost::mutex::scoped_lock lock( m_mutex );

    stream_size_t areaId = reader.ReadUlong();

    m_queue.push( areaId );
    m_ptrCondition->notify_all();
}
c++ ub
Re: UB ?
От: uzhas Ниоткуда  
Дата: 06.10.17 18:04
Оценка: +1
Я не вижу тут проблем, доступ к очереди всегда защищён. Наличие лока мешает проводить оптимизацию, которую вы описали. Почему родился вопрос?))
Re[2]: UB ?
От: dcb_BanDos Чехия  
Дата: 09.10.17 07:37
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Я не вижу тут проблем, доступ к очереди всегда защищён. Наличие лока мешает проводить оптимизацию, которую вы описали. Почему родился вопрос?))


Видимо пятница-вечер родила этот вопрос
Re: UB ?
От: Alexander G Украина  
Дата: 09.10.17 10:24
Оценка: +1
Здравствуйте, dcb_BanDos, Вы писали:

_BD>Два потока, один дергает WaitAndPopInfo, второй Push. Может ли компилятор прооптимизировать while( m_queue.empty() ) до while(true/false)?


Немного придирок к коду (не по существу вопроса):

* Pop на базе Try Pop с освобождением и повторным захватом лока выглядит субоптимально
* notify_all лучше бы вызывать не под локом, под локом только само заталкивание в очередь
* Таймаут, по которому не выходим из ожидания, а проверяем, не добавил ли кто вдруг в очередь без уведомления. Если кроме приведенного Push никак в очередь не добавляют, это выглядит лишним
Русский военный корабль идёт ко дну!
Re: UB ?
От: Alexander G Украина  
Дата: 09.10.17 13:12
Оценка:
Здравствуйте, dcb_BanDos, Вы писали:

_BD> Может ли компилятор прооптимизировать while( m_queue.empty() ) до while(true/false)?


timed_wait, как и wait внутри себя отпускает мьютекс, а потом снова захватывают.
(в этом отпускании/захвате и есть те самые барьеры, запрещающие думать, что m_queue.empty() не поменялся.

        boost::mutex::scoped_lock lock( m_mutex );
        while( m_queue.empty() )
        {
            boost::system_time const timeoutAbsTime = boost::get_system_time() + boost::posix_time::milliseconds( queueConditionTimeout );
            m_ptrCondition->timed_wait( lock, timeoutAbsTime );
        }
Русский военный корабль идёт ко дну!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.