1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown An example that shows how to implement the monitor synchronization concept. 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown See also http://en.wikipedia.org/wiki/Monitor_(synchronization) for more 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown information about this concept. 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ---------------------------------------------------------------- 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Notice that the following BSD-style license applies to this one 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file (monitor_example.cpp) only. The rest of Valgrind is licensed 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown under the terms of the GNU General Public License, version 2, 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unless otherwise indicated. See the COPYING file in the source 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown distribution for details. 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ---------------------------------------------------------------- 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of DRD, a heavyweight Valgrind tool for detecting 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errors in multithreaded programs. 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Copyright (C) 2008-2009 Bart Van Assche. All rights reserved. 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Redistribution and use in source and binary forms, with or without 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modification, are permitted provided that the following conditions 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are met: 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1. Redistributions of source code must retain the above copyright 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notice, this list of conditions and the following disclaimer. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2. The origin of this software must not be misrepresented; you must 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not claim that you wrote the original software. If you use this 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown software in a product, an acknowledgment in the product 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown documentation would be appreciated but is not required. 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3. Altered source versions must be plainly marked as such, and must 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not be misrepresented as being the original software. 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4. The name of the author may not be used to endorse or promote 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown products derived from this software without specific prior written 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown permission. 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ---------------------------------------------------------------- 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Notice that the above BSD-style license applies to this one 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown file (monitor_example.cpp) only. The rest of Valgrind is licensed 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown under the terms of the GNU General Public License, version 2, 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unless otherwise indicated. See the COPYING file in the source 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown distribution for details. 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ---------------------------------------------------------------- 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _GNU_SOURCE 1 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h" 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <cassert> 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <iostream> 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass Monitor 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownpublic: 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Monitor() 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : m_mutex() 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown , m_cond() 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown , m_owner() 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown , m_recursion_count() 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutexattr_t mutexattr; 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutexattr_init(&mutexattr); 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_init(&m_mutex, &mutexattr); 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutexattr_destroy(&mutexattr); 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_condattr_t condattr; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_condattr_init(&condattr); 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_init(&m_cond, &condattr); 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_condattr_destroy(&condattr); 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ~Monitor() 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(m_recursion_count == 0); 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_destroy(&m_cond); 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_destroy(&m_mutex); 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void lock() 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_lock(&m_mutex); 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(m_recursion_count >= 0); 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (++m_recursion_count == 1) 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_owner = pthread_self(); 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void unlock() 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_recursion_count--; 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(m_recursion_count >= 0); 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock(&m_mutex); 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void wait() 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(m_recursion_count == 1); 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(m_owner == pthread_self()); 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_recursion_count--; 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_wait(&m_cond, &m_mutex); 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_recursion_count++; 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_owner = pthread_self(); 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void signal() 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(m_recursion_count > 0); 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_signal(&m_cond); 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void broadcast_signal() 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(m_recursion_count > 0); 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_broadcast(&m_cond); 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bool is_locked_by_self() 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bool result; 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_lock(&m_mutex); 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result = m_recursion_count > 0 && m_owner == pthread_self(); 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock(&m_mutex); 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return result; 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownprivate: 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Monitor(const Monitor&); 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Monitor& operator=(const Monitor&); 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t m_mutex; 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t m_cond; 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t m_owner; 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int m_recursion_count; 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass ScopedLock 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownpublic: 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ScopedLock(Monitor& m) 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : m_monitor(m) 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown , m_locked(false) 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { lock(); } 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ~ScopedLock() 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { if (m_locked) unlock(); } 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void lock() 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { assert(! m_locked); m_monitor.lock(); m_locked = true; } 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void unlock() 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { assert(m_locked); m_locked = false; m_monitor.unlock(); } 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownprivate: 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ScopedLock(const ScopedLock&); 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ScopedLock& operator=(const ScopedLock&); 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Monitor& m_monitor; 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bool m_locked; 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass StateVariable 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownpublic: 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown StateVariable() 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : m_state() 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { } 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int get() 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ScopedLock sl(m_monitor); 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return m_state; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void set(const int state) 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ScopedLock sl(m_monitor); 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_state = state; 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_monitor.signal(); 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void wait(const int state) 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ScopedLock sl(m_monitor); 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (m_state != state) 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown m_monitor.wait(); 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownprivate: 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Monitor m_monitor; 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int m_state; 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic StateVariable s_sv; 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread_func(void*) 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_sv.wait(1); 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_sv.set(2); 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_sv.wait(3); 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_sv.set(4); 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(int, char**) 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t tid; 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&tid, 0, thread_func, 0); 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_sv.set(1); 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_sv.wait(2); 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_sv.set(3); 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown s_sv.wait(4); 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_join(tid, 0); 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown std::cerr << "Finished successfully.\n"; 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 232