mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-12 06:11:37 +00:00
Added a regression test called monitor_example.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@8646
This commit is contained in:
175
drd/tests/monitor_example.cpp
Normal file
175
drd/tests/monitor_example.cpp
Normal file
@@ -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 <bart.vanassche@gmail.com>
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
Reference in New Issue
Block a user