Аналог windows event в с++

Dima T
Дата: 17.04.2015 07:50:19
Надо пробуждать поток по мере необходимиости. С event все просто: ожидающий висит на WaitForSingleObject(), тот кому он потребовался вызывает SetEvent(), пример:
#include <windows.h>
#include <thread>

HANDLE event = NULL;

void test_thread()
{
	int cnt = 0;
	while(cnt < 5) {
		WaitForSingleObject(event, INFINITE); // ожидаем задание
		printf("cnt = %d\n", cnt++); // обрабатываем задание
	}
}

int main(int argc, char* argv[])
{
	event = CreateEvent(NULL, FALSE, FALSE, NULL);
	std::thread th(test_thread);
	for(int i = 0; i < 5; i++) {
		Sleep(1000); // готовим задание
		printf("i = %d\n", i);
		SetEvent(event); // пробуждаем поток для обработки задания
	}
	th.join();
	CloseHandle(event);
	system("pause");
}

В линуксе подобное можно сделать семафорами.

Как сделать подобное средствами С++ ? <mutex> не подходит, т.к. unlock() может выполнить только тот поток который вызывал lock().
MasterZiv
Дата: 17.04.2015 08:00:33
Dima T,

там же есть condition variables
Dima T
Дата: 17.04.2015 08:13:38
MasterZiv
там же есть condition variables

Я читал про них, но так и не понял как их в такую конструкцию вписать. Еще почитаю
locked
Дата: 17.04.2015 08:49:59
Dima T,

15105667
Dima T
Дата: 17.04.2015 09:44:30
Немного разобрался с condition_variable
Непонятно зачем перед командой на пробуждение (notify_one()) надо unique_lock. Во всех примерах так.
#include <thread>
#include <condition_variable>

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

void test_thread()
{
	int cnt = 0;
	while(cnt < 5) {
		std::unique_lock<std::mutex> lck(mtx);
		cv.wait(lck); // ожидаем задание
		printf("%5d: work %d\n", clock(), cnt); // обрабатываем задание
	}
}

int main(int argc, char* argv[])
{
	std::thread th(test_thread);
	for(int i = 0; i < 5; i++) {
		Sleep(1000); // готовим задание
		printf("%5d: task %d\n", clock(), i);
		std::unique_lock<std::mutex> lck(mtx); // зачем ???
		cv.notify_one(); // пробуждаем поток для обработки задания
	}
	th.join();
	system("pause");
}
locked
Дата: 17.04.2015 10:14:24
Dima T,

потому что notify_ разблокирует его.
Dima T
Дата: 17.04.2015 10:31:39
locked
Dima T,

потому что notify_ разблокирует его.

Если строчку unique_lock убрать - работает точно также.

Думаю она нужна чтобы одновременно два notify_ не вызвать с двух разных потоков. Но не уверен что правильно понимаю. Где бы поподробнее почитать как <condition_variable> устроены, желательно по-русски.
locked
Дата: 17.04.2015 11:10:37
Dima T
locked
Dima T,

потому что notify_ разблокирует его.

Если строчку unique_lock убрать - работает точно также.

Думаю она нужна чтобы одновременно два notify_ не вызвать с двух разных потоков. Но не уверен что правильно понимаю. Где бы поподробнее почитать как <condition_variable> устроены, желательно по-русски.


немного подзабыл. захват мютекса перед вызовом notify нужен только для монопольного доступа к ресурсам. например добавление задания в очередь для запускаемой thread. мютекс нужно освободить. т.к. пробуждаемая thread его захватывает внутри wait. по выходу из wait мютекс захвачен. thread может взять задание из очереди и _должна_ освободить мютекс.

типа такого

#include <thread>
#include <condition_variable>

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

void test_thread()
{
	int cnt = 0;
	while(cnt < 5) {
          { // область действия мютекса
		std::unique_lock<std::mutex> lck(mtx);
		cv.wait(lck); // ожидаем задание
// читаем задание для thread
          } // освобождаем мютекс
		printf("%5d: work %d\n", clock(), cnt); // обрабатываем задание
	}
}

int main(int argc, char* argv[])
{
	std::thread th(test_thread);
	for(int i = 0; i < 5; i++) {
		Sleep(1000); // готовим задание
		printf("%5d: task %d\n", clock(), i);
		std::unique_lock<std::mutex> lck(mtx); // зачем ???
// добавляем задание для thread в очередь
		cv.notify_one(); // пробуждаем поток для обработки задания
	}
	th.join();
	system("pause");
}
Dima T
Дата: 17.04.2015 12:19:53
locked
немного подзабыл. захват мютекса перед вызовом notify нужен только для монопольного доступа к ресурсам. например добавление задания в очередь для запускаемой thread. мютекс нужно освободить. т.к. пробуждаемая thread его захватывает внутри wait. по выходу из wait мютекс захвачен. thread может взять задание из очереди и _должна_ освободить мютекс.
...

Спасибо. Теперь понял.
MasterZiv
Дата: 17.04.2015 12:57:16
Dima T,

ну кстати я тоже не понимаю, почему бы аналог виндовых event не сделать в xnix.
мне они кажутся более понятными , чем cond var.