int run_threads() { // start 3 _threads and wait until they're done std::unique_ptr<Value> value(new Value()); pthread_mutex_init(&_mutex, nullptr); _threads.create_thread(PRODUCER, (void *) producer_routine, (void *) &*value); _threads.create_thread(CONSUMER, (void *) consumer_routine, (void *) &*value); _threads.create_thread(INTERRUPTOR, (void *) consumer_interruptor_routine, nullptr); _threads.run_threads(); // return sum of update values seen by consumer std::shared_ptr<int> result(new int(0)); pthread_join(_threads.get(PRODUCER)->get(), nullptr); pthread_join(_threads.get(CONSUMER)->get(), (void **) &result); pthread_join(_threads.get(INTERRUPTOR)->get(), nullptr); pthread_mutex_destroy(&_mutex); return *result; }
void* consumer_routine(void* arg) { // notify about start _threads.get(CONSUMER)->set_cancel_state_enabled(false); _threads.get(CONSUMER)->notify_thread_started(&_mutex); // allocate value for result int * sum = new int(0); // for every update issued by producer, read the value and add to sum while (true) { _exchanger.start_exchanging(&_mutex); _exchanger.wait_for_exchange_started(&_mutex); if (!_threads.get(PRODUCER)->is_running()) { _exchanger.exchange(); _exchanger.end_exchanging(&_mutex); break; } *sum += ((Value *) arg)->get(); _exchanger.exchange(); _exchanger.end_exchanging(&_mutex); } _threads.get(CONSUMER)->set_cancel_state_enabled(true); // return pointer to result _threads.get(CONSUMER)->notify_thread_stopped(&_mutex); return sum; }
void* consumer_interruptor_routine(void* arg) { // wait for consumer to start _threads.get(CONSUMER)->wait_for_running(&_mutex); // interrupt consumer while producer is running while (_threads.get(PRODUCER)->is_running()) { _threads.get(CONSUMER)->cancel(); } _threads.get(INTERRUPTOR)->notify_thread_stopped(&_mutex); return nullptr; }
void* producer_routine(void* arg) { // Wait for consumer to start _threads.get(CONSUMER)->wait_for_running(&_mutex); _threads.get(PRODUCER)->notify_thread_started(&_mutex); // Read data, loop through each value and update the value, notify consumer, wait for consumer to process int value = 0; while (std::cin >> value) { _exchanger.start_exchanging(&_mutex); _exchanger.init_exchanging(); ((Value *) arg)->update(value); _exchanger.wait_for_exchange_finished(&_mutex); _exchanger.end_exchanging(&_mutex); } _exchanger.start_exchanging(&_mutex); _exchanger.init_exchanging(); _threads.get(PRODUCER)->unsafe_notify_thread_stopped(&_mutex); _exchanger.wait_for_exchange_finished(&_mutex); _exchanger.end_exchanging(&_mutex); return nullptr; }