condition_variable 테스트

서론

c++11 의 condition_variable 에 대해서는 유투브 코드없는 프로그래밍 의 강의를 보시는 것을 추천합니다. 가능하면 관련 강의를 모두 들으시기 바랍니다.

provider/consumer 패턴을 사용할 일이 많기 때문에, condition_variable 에 대해 보다 확실하기 위한 테스트 입니다.

준비

void wait( std::unique_lock<std::mutex>& lock, Predicate stop_waiting );

condition_variable의 메소드 wait() 에 파라메터로 들어가는 stop_waiting function 조건에 대해서 테스트

코드

#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
/// compile : g++ -std=c++11 -pthread cv_test.cpp -o cv_test && ./cv_test
std::condition_variable _cv;
std::mutex _mutex;
int32_t _value;
int32_t _running;
void provider()
{
_running = true;
while (_running) {
{
std::lock_guard<std::mutex> lock(_mutex);
_value++;
}
_cv.notify_one();
printf("%s %4d %s : notify value:%d\n", __FILE__, __LINE__, __func__, _value);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
printf("%s %4d %s : out\n", __FILE__, __LINE__, __func__);
}
void consumer()
{
_running = true;
while (_running) {
std::unique_lock<std::mutex> lock(_mutex);
_cv.wait(lock, []() -> bool {
bool b = !_running || _value >= 10;
printf("%s %4d %s : running:%d value:%d return:%d\n", __FILE__, __LINE__, __func__, _running, _value, b);
return b;
});
printf("%s %4d %s : running:%d value:%d out\n", __FILE__, __LINE__, __func__, _running, _value);
_value = 0;
}
printf("%s %4d %s : out\n", __FILE__, __LINE__, __func__);
}
int main(int argc, char* argv[])
{
std::thread provider_th(provider);
std::thread consumer_th(consumer);
std::this_thread::sleep_for(std::chrono::seconds(10));
_running = false;
_cv.notify_all();
provider_th.join();
consumer_th.join();
return 0;
}
view raw cv_test.cpp hosted with ❤ by GitHub

결과 및 분석

결과1

main.cpp   24 provider : notify value:1
main.cpp   37 operator() : running:1 value:1 return:0
main.cpp   24 provider : notify value:2
main.cpp   37 operator() : running:1 value:2 return:0
main.cpp   24 provider : notify value:3
main.cpp   37 operator() : running:1 value:3 return:0
main.cpp   24 provider : notify value:4
main.cpp   37 operator() : running:1 value:4 return:0
main.cpp   24 provider : notify value:5
main.cpp   37 operator() : running:1 value:5 return:0
main.cpp   24 provider : notify value:6
main.cpp   37 operator() : running:1 value:6 return:0
main.cpp   24 provider : notify value:7
main.cpp   37 operator() : running:1 value:7 return:0
main.cpp   24 provider : notify value:8
main.cpp   37 operator() : running:1 value:8 return:0
main.cpp   24 provider : notify value:9
main.cpp   37 operator() : running:1 value:9 return:0
main.cpp   24 provider : notify value:10
main.cpp   37 operator() : running:1 value:10 return:1
main.cpp   40 consumer : running:1 value:10 out


provider에서 value++ 후 notify_one

consumer의 wait() stop_waiting에서 return false이므로 다시 wait

...

provider에서 value++ 후 notify_one

consumer의 wait() stop_waiting에서 value가 10이 넘어 return true이므로 wait 종료


결과2

cv_test.cpp   37 operator() : running:1 value:0 return:0
cv_test.cpp   53 main : out
cv_test.cpp   37 operator() : running:0 value:0 return:1
cv_test.cpp   40 consumer : running:0 value:0 out
cv_test.cpp   43 consumer : out
cv_test.cpp   27 provider : out


main에서 out 과 함께 _running = false, cv.notify_all(), thread join으로 대기

consumer의 wait() stop_waiting에서 value가 0이나 running == false 로 return true로 wait 종료

while 종료와 함께 consumer thread 종료

provider 종료

main 종료


의미

wait 가 wakeup 하더라도 func이 return true인 경우에만 wait 종료임을 확인함.

stop_waiting에서 return의 의미를 확실히함



댓글

이 블로그의 인기 게시물

WSL2 Ubuntu 20.04 및 네트워크 설정

리눅스 멀티코어를 사용하는 tar 압축/해제

WSL에 X-Window로 Terminator 설치하고 Minicom까지