2016-03-16 5 views
0

Я хотел знать, что лучший способ блокировать метод до тех пор, пока условие не станет истинным.Как заблокировать до тех пор, пока не будет выполнено условие

Пример:

class DoWork 
{ 
    int projects_completed; 
    public: 
    ..... 
    void WaitForProjectsCompleted() 
    { 
    ---->//How do I block until projects_completed == 12; 
    } 
}; 

Я хочу, чтобы использовать его в качестве такого

class foo 
{ 
.... 
void someMethod() 
{ 
    DoWork work; 
    work.WaitForProjectsCompleted();//This should block 
} 
} 
+0

Что вы имеете в виду «block»?, Вы работаете с несколькими задачами? вы хотите выйти из функции/метода? –

+0

YEs Класс DoWork использует несколько потоков, которые увеличивают атомную переменную-член. Я бы хотел, чтобы someMethod() не возвращался, пока атомная переменная не имеет определенного значения. 10 – MistyD

ответ

2

Предполагая, что есть еще одна нить, которая на самом деле собирается делать что-то здесь, легкая вещь, чтобы использовать это std::condition_variable:

std::condition_variable cv; 
std::mutex mtx; 

void WaitForProjectsCompleted() { 
    std::unique_lock<std::mutex> lk(mtx); 
    cv.wait(mtx, [this]{ return projects_completed >= 12; }); 
} 

Где-то еще, какая-то другая функция-член может сделать:

void CompleteProject() { 
    { 
     std::lock_guard<std::mutex> lk(mtx); 
     ++projects_completed; 
    } 
    cv.notify_one(); // let the waiter know 
} 

Если projects_completed атомная, вы могли бы вместо того, чтобы просто отжим:

void WaitForProjectsCompleted() { 
    while (projects_completed < 12) ; 
} 

Это будет работать нормально тоже.

+3

Есть ли что-то о 'std :: atomic', которое я не получаю, что делает спин-решение не ужасным? –

+2

Хороший ответ до тех пор, пока не будет предложено атомное ожидание-ожидание, которое должно по крайней мере прийти с объяснением потенциальных проблем .... –

+0

@BarryTheHatchet Почему ужасно? – Barry

1

Переменные состояния - отличный примитив синхронизации, и в моем личном опыте это инструмент, с которым я отвечаю, до 95% ситуаций синхронизации/потоковой передачи.

Если у вас нет C++ 11, вы можете использовать boost::condition_variable.
В этом случае у вас не будет версии wait с предикатом (потому что нет lambdas в C++ 03). Поэтому вам абсолютно необходимо запомнить цикл проверки состояния. Как объяснено в документации:

boost::unique_lock<boost::mutex> lock(mut); 
while (projects_completed < 12) 
{ 
    wait(lock); 
} 

сравни:
http://www.boost.org/doc/libs/1_58_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref

Это потому, что вы не получаете никаких гарантий, что условие выполнено после уведомления, в частности потому, что замок может быть приобретено другим потоком в междоузлии между разблокировкой и уведомлением. Также может произойти ложное пробуждение.

Я также написал статью об этом:
http://www.gamedev.net/page/resources/_/technical/general-programming/multithreading-r3048

Кроме того, если вы используете timed_wait (и я рекомендую его, как это часто снижает priority inversion), еще одна ловушка, чтобы не попасть в это тайм-аут из-за петли вы не можете использовать относительный тайм-аут (например, 2 секунды), вам нужно абсолютное системное время, определенное до ввода цикла.
boost делает его очень чистым с этой техникой:

system_time const timeout = get_system_time() + posix_time::seconds(2); 

О картине спин блокировки, предложенной Барри, я не рекомендовал бы это, если вы не в реальной среде времени, как игровая приставка 3/4 или эквивалент. Или, если вы не уверены, что это не продлится более нескольких секунд.
С помощью блокировки спина вы теряете электроэнергию, и у вас не останется шанса, что CPU войдет в состояние ожидания (шаг скорости c.f intel).
Это также имеет последствия для справедливости и планирования, как описано в Википедии:
https://en.wikipedia.org/wiki/Spinlock

Наконец, если у вас нет импульс, так как Windows Vista мы получаем уроженцы Win32 функции:
SleepConditionVariableCS
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686301(v=vs.85).aspx

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