|
From: <sv...@va...> - 2008-10-05 17:38:11
|
Author: bart Date: 2008-10-05 18:37:06 +0100 (Sun, 05 Oct 2008) New Revision: 8646 Log: Added a regression test called monitor_example. Added: trunk/drd/tests/monitor_example.cpp trunk/drd/tests/monitor_example.stderr.exp trunk/drd/tests/monitor_example.vgtest Modified: trunk/drd/tests/ trunk/drd/tests/Makefile.am Property changes on: trunk/drd/tests ___________________________________________________________________ Name: svn:ignore - *.stderr.diff* *.stderr.out *.stdout.diff* *.stdout.out .deps atomic_var drd_bitmap_test fp_race hg01_all_ok hg02_deadlock hg03_inherit hg04_race hg05_race2 hg06_readshared hold_lock linuxthreads_det Makefile Makefile.in matinv memory_allocation new_delete omp_matinv omp_prime pth_barrier pth_barrier_reinit pth_broadcast pth_cancel_locked pth_cond_race pth_create_chain pth_detached pth_detached_sem pth_inconsistent_cond_wait pth_spinlock qt4_mutex qt4_rwlock qt4_semaphore recursive_mutex rwlock_race rwlock_test sem_as_mutex sigalrm tc01_simple_race tc02_simple_tls tc03_re_excl tc04_free_lock tc05_simple_race tc06_two_races tc07_hbl1 tc08_hbl2 tc09_bad_unlock tc10_rec_lock tc11_XCHG tc12_rwl_trivial tc13_laog1 tc15_laog_lockdel tc16_byterace tc17_sembar tc18_semabuse tc19_shadowmem tc20_verifywrap tc21_pthonce tc22_exit_w_lock tc23_bogus_condwait tc24_nonzero_sem trylock vg_regtest.tmp* + *.stderr.diff* *.stderr.out *.stdout.diff* *.stdout.out .deps atomic_var drd_bitmap_test fp_race hg01_all_ok hg02_deadlock hg03_inherit hg04_race hg05_race2 hg06_readshared hold_lock linuxthreads_det Makefile Makefile.in matinv memory_allocation monitor_example new_delete omp_matinv omp_prime pth_barrier pth_barrier_reinit pth_broadcast pth_cancel_locked pth_cond_race pth_create_chain pth_detached pth_detached_sem pth_inconsistent_cond_wait pth_spinlock qt4_mutex qt4_rwlock qt4_semaphore recursive_mutex rwlock_race rwlock_test sem_as_mutex sigalrm tc01_simple_race tc02_simple_tls tc03_re_excl tc04_free_lock tc05_simple_race tc06_two_races tc07_hbl1 tc08_hbl2 tc09_bad_unlock tc10_rec_lock tc11_XCHG tc12_rwl_trivial tc13_laog1 tc15_laog_lockdel tc16_byterace tc17_sembar tc18_semabuse tc19_shadowmem tc20_verifywrap tc21_pthonce tc22_exit_w_lock tc23_bogus_condwait tc24_nonzero_sem trylock vg_regtest.tmp* Modified: trunk/drd/tests/Makefile.am =================================================================== --- trunk/drd/tests/Makefile.am 2008-09-28 12:31:45 UTC (rev 8645) +++ trunk/drd/tests/Makefile.am 2008-10-05 17:37:06 UTC (rev 8646) @@ -54,6 +54,8 @@ matinv.vgtest \ memory_allocation.stderr.exp \ memory_allocation.vgtest \ + monitor_example.stderr.exp \ + monitor_example.vgtest \ new_delete.stderr.exp \ new_delete.vgtest \ omp_matinv.stderr.exp \ @@ -201,6 +203,7 @@ linuxthreads_det \ matinv \ memory_allocation \ + monitor_example \ new_delete \ pth_barrier \ pth_barrier_reinit \ @@ -291,6 +294,9 @@ memory_allocation_SOURCES = memory_allocation.c +monitor_example_SOURCES = monitor_example.cpp +monitor_example_LDADD = -lpthread + new_delete_SOURCES = new_delete.cpp pth_barrier_SOURCES = pth_barrier.c Added: trunk/drd/tests/monitor_example.cpp =================================================================== --- trunk/drd/tests/monitor_example.cpp (rev 0) +++ trunk/drd/tests/monitor_example.cpp 2008-10-05 17:37:06 UTC (rev 8646) @@ -0,0 +1,175 @@ +// An example that shows how to implement the monitor synchronization concept. +// See also http://en.wikipedia.org/wiki/Monitor_(synchronization). +// +// Copyright (C) 2008 Bart Van Assche <bar...@gm...> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Apache License version 2.0 +// (see also http://www.apache.org/licenses/LICENSE-2.0.txt). + + +#define _GNU_SOURCE 1 + + +#include <cassert> +#include <iostream> +#include <pthread.h> + + +class Monitor +{ +public: + Monitor() + : m_mutex() + , m_cond() + , m_owner() + , m_recursion_count() + { + pthread_mutexattr_t mutexattr; + pthread_mutexattr_init(&mutexattr); + pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_mutex, &mutexattr); + pthread_mutexattr_destroy(&mutexattr); + pthread_condattr_t condattr; + pthread_condattr_init(&condattr); + pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); + pthread_cond_init(&m_cond, 0); + pthread_condattr_destroy(&condattr); + } + ~Monitor() + { + assert(m_recursion_count == 0); + pthread_cond_destroy(&m_cond); + pthread_mutex_destroy(&m_mutex); + } + void lock() + { + pthread_mutex_lock(&m_mutex); + assert(m_recursion_count >= 0); + if (++m_recursion_count == 1) + { + m_owner = pthread_self(); + } + } + void unlock() + { + m_recursion_count--; + assert(m_recursion_count >= 0); + pthread_mutex_unlock(&m_mutex); + } + void wait() + { + assert(m_recursion_count == 1); + assert(m_owner == pthread_self()); + m_recursion_count--; + pthread_cond_wait(&m_cond, &m_mutex); + m_recursion_count++; + m_owner = pthread_self(); + } + void signal() + { + assert(m_recursion_count > 0); + pthread_cond_signal(&m_cond); + } + void broadcast_signal() + { + assert(m_recursion_count > 0); + pthread_cond_broadcast(&m_cond); + } + bool is_locked_by_self() + { + bool result; + pthread_mutex_lock(&m_mutex); + result = m_recursion_count > 0 && m_owner == pthread_self(); + pthread_mutex_unlock(&m_mutex); + return result; + } + +private: + Monitor(const Monitor&); + Monitor& operator=(const Monitor&); + + pthread_mutex_t m_mutex; + pthread_cond_t m_cond; + pthread_t m_owner; + int m_recursion_count; +}; + + +class ScopedLock +{ +public: + ScopedLock(Monitor& m) + : m_monitor(m) + , m_locked(false) + { lock(); } + ~ScopedLock() + { if (m_locked) unlock(); } + void lock() + { assert(! m_locked); m_monitor.lock(); m_locked = true; } + void unlock() + { assert(m_locked); m_locked = false; m_monitor.unlock(); } + +private: + ScopedLock(const ScopedLock&); + ScopedLock& operator=(const ScopedLock&); + + Monitor& m_monitor; + bool m_locked; +}; + + +class StateVariable +{ +public: + StateVariable() + : m_state() + { } + int get() + { + ScopedLock sl(m_monitor); + return m_state; + } + void set(const int state) + { + ScopedLock sl(m_monitor); + m_state = state; + m_monitor.signal(); + } + void wait(const int state) + { + ScopedLock sl(m_monitor); + while (m_state != state) + m_monitor.wait(); + } + +private: + Monitor m_monitor; + int m_state; +}; + + +static StateVariable s_sv; + + +static void* thread_func(void*) +{ + s_sv.wait(1); + s_sv.set(2); + s_sv.wait(3); + s_sv.set(4); + return 0; +} + +int main(int, char**) +{ + pthread_t tid; + pthread_create(&tid, 0, thread_func, 0); + s_sv.set(1); + s_sv.wait(2); + s_sv.set(3); + s_sv.wait(4); + pthread_join(tid, 0); + std::cerr << "Finished successfully.\n"; + return 0; +} Added: trunk/drd/tests/monitor_example.stderr.exp =================================================================== --- trunk/drd/tests/monitor_example.stderr.exp (rev 0) +++ trunk/drd/tests/monitor_example.stderr.exp 2008-10-05 17:37:06 UTC (rev 8646) @@ -0,0 +1,4 @@ + +Finished successfully. + +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) Added: trunk/drd/tests/monitor_example.vgtest =================================================================== --- trunk/drd/tests/monitor_example.vgtest (rev 0) +++ trunk/drd/tests/monitor_example.vgtest 2008-10-05 17:37:06 UTC (rev 8646) @@ -0,0 +1,2 @@ +prereq: ./supported_libpthread +prog: monitor_example |