2015-07-07 3 views
0

У меня есть следующий метод класса:C++ условного ожидания прекращает выполнение

myclass::concurFnc(bool changingVar) 
{ 
    int i; 
    mIdMutex.lock(); 
    i = mId++; 
    mIdMutex.unlock; 

    std::cout << "Try Waiting: " << i << std::endl; 
    std::mutex waitValidMutex; 
    std::unique_lock<std::mutex> l(waitValidMutex); 
    mNoOtherThreadDiffCompareVal.wait(l, [this, &changingVar]() 
    { 
     mSemMutex.lock(); 
     bool result = false; 
     if(myclass::staticVar == changingVar) 
     { 
      std::cout << "Same var : " << changingVar << i << std::endl; 
      result = true; 
      --mSem; 
     } else if(mSem == 1) 
     { 
      std::cout << "Only one in crit section: " << i << std::endl; 
      --mSem; 
      myclass::staticVar = changingVar; 
      result = true; 
     } else 
     { 
      std::cout << "wait: " << i << std::endl; 
      result = false; 
     } 
     std::cout << "Sem is now " << mSem << std::endl; 
     mSemMutex.unlock(); 
     return result; 
    }); 

    //DO STUFF 

    mSemMutex.lock(); 
    ++mSem; 
    std::cout << "In the end sem is: " << mSem << std::endl; 
    mSemMutex.unlock(); 
    mNoOtherThreadDiffCompareVal.notify_all(); 
} 

//class Member Variables 
std::mutex mSemMutex; 
std::mutex mIdMutex; 
std::condition_variable mNoOtherThreadDiffCompareVal; 
int32_t mSem; 
int32_t mId; 

myclass::myclass() : mSem(1), mId(0) 
{ 
} 

void myclass::startThreads() 
{ 
    const int AMOUNT_OF_PROCESSES = 3 
    std::vector<std::shared_ptr<boost::thread> > processes; 
    for (size_t t_id = 0; t_id < AMOUNT_OF_PROCESSES; ++t_id) 
    { 
     bool changingVar = getVarSomewhere(); 
     std::shared_ptr<boost::thread> thread_ptr(new boost::thread(&myclass::concurFnc, this, changingVar)); 
     processes.push_back(thread_ptr); 
    } 

    for (size_t t_id = 0; t_id < AMOUNT_OF_PROCESSES; ++t_id) { 
     processes[t_id]->join(); 
    } 
} 

Это должно позволить ввести // DO STUFF раздел, если changingVar такого же, как для всех других абонентов, которые в настоящее время находятся внутри // DO STUFF (или его единственный) Функция называется одновременной из функций в boost :: threads.

Иногда сложилось, что выполнение останавливается, потому что он продолжает ожидать, хотя mSem 1 и notify_all() должны были названы

выход перед казнью остановками:

wait: 3248 
Sem is now 0 
Try Waiting: 3249 
wait: 3249 
Sem is now 0 
In the end sem is: 1 
Only one in crit section: 3249 
Sem is now 0 
Try Waiting: 3250 
wait: 3250 
Sem is now 0 
In the end sem is: 1 
Only one in crit section: 3250 
Sem is now 0 
In the end sem is: 1 
Try Waiting: 3251 
Same comp val : 0 of: 3251 
Sem is now 0 
.In the end sem is: 1 

До сих пор я мог на самом деле не воспроизводят его.

Программа начала работать снова. Mabey это было потому, что я прикрепил к нему gdb, или была какая-то огромная задержка.

+0

Возможно, 'changeVar' следует передать в' concurFnc' по ссылке? –

+0

не может видеть ничего плохого с кодом, который вы показали; поэтому проблема должна быть в коде, который вы не показывали ... – Pandrei

+0

Какова цель 'waitValidMutex'? Он не разделяется между любыми потоками. – molbdnilo

ответ

1

Ваш шаблон использования для переменной условия очень странный.

Мьютекс, переданный в функцию wait для переменной условия, всегда должен быть тем, который защищает условие, которое вы ожидаете, которое здесь mSemMutex.

Это имеет смысл, поскольку для проверки того, выполняется ли ожидаемое условие, вам необходимо заблокировать этот мьютекс. Имея это в виду, вы можете полностью избавиться от waitValidMutex и заменить все его применения на mSemMutex.

отметить также, что в настоящее время, так как waitValidMutex является локальным мьютекс, вы на самом деле risk undefined behavior when calling wait:

Вызов этой функции, если lock.mutex() это не то же мьютекс, как один используется всеми другими нитями, которые в настоящее время ждут на той же переменной условия является неопределенным поведением.

+0

Я не думаю, что это правда. Поскольку я не разделяю waitValidMutex, я испытываю параллелизм. Я проверил его, добавив больше вывода. Я не ожидаю mSemMutex, так как должно быть возможно ввести // DO STUFF, когда staticVar и changeVar равны –

+0

О, извините, я не заметил, что мьютекс был локальным. В этом случае дело обстоит хуже. Я отредактирую ответ. – ComicSansMS

+0

О, okey, чем переменные состояния, не является таким путем. Я буду придерживаться петли опроса –

Смежные вопросы