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; | |
} |
결과 및 분석
결과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 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의 의미를 확실히함
댓글
댓글 쓰기