Files
fail/deprecated/old-utils/Signal.hpp

136 lines
3.5 KiB
C++

#ifndef __SIGNAL_HPP__
#define __SIGNAL_HPP__
// FIXME: This is deprecated stuff. Delete it.
#include <cassert>
#include <memory>
#include <iostream>
#ifndef __puma
#include <boost/thread.hpp>
#include <boost/interprocess/sync/named_semaphore.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
#endif
namespace fi
{
#ifndef __puma
typedef boost::mutex Mutex; // lock/unlock
typedef boost::mutex::scoped_lock ScopeLock; // use RAII with lock/unlock mechanism
typedef boost::condition_variable ConditionVariable; // wait/notify_one
#else
typedef int Mutex;
typedef int ScopeLock;
typedef int ConditionVariable;
#endif
// Simulate a "private" semaphore using boost-mechanisms:
class Semaphore
{
private:
Mutex m_Mutex;
ConditionVariable m_CondVar;
unsigned long m_Value;
public:
// Create a semaphore object based on a mutex and a condition variable
// and initialize it to value "init".
Semaphore(unsigned long init = 0) : m_Value(init) { }
void post()
{
ScopeLock lock(m_Mutex);
++m_Value; // increase semaphore value:
#ifndef __puma
m_CondVar.notify_one(); // wake up other thread, currently waiting on condition var.
#endif
}
void wait()
{
ScopeLock lock(m_Mutex);
#ifndef __puma
while(!m_Value) // "wait-if-zero"
m_CondVar.wait(lock);
#endif
--m_Value; // decrease semaphore value
}
};
class Signal
{
private:
static Mutex m_InstanceMutex; // used to sync calls to getInst()
static std::auto_ptr<Signal> m_This; // the one and only instance
Semaphore m_semBochs;
Semaphore m_semContr;
Semaphore m_semSimCtrl;
bool m_Locked; // prevent misuse of thread-sync
// Singleton class (forbid creation, copying and assignment):
Signal()
: m_semBochs(0), m_semContr(0),
m_semSimCtrl(0), m_Locked(false) { }
Signal(Signal const& s)
: m_semBochs(), m_semContr(),
m_semSimCtrl(), m_Locked(false) { } // never called.
Signal& operator=(Signal const&) { return *this; } // dito.
~Signal() { }
friend class std::auto_ptr<Signal>;
public:
static Signal& getInst()
{
ScopeLock lock(m_InstanceMutex); // lock/unlock handled by RAII principle
if(!m_This.get())
m_This.reset(new Signal());
return (*m_This);
}
// Called from Experiment-Controller class ("beyond Bochs"):
void lockExperiment()
{
assert(!m_Locked &&
"[Signal::lockExperiment]: lockExperiment called twice without calling unlockExperiment() in between.");
m_Locked = true;
m_semContr.wait(); // suspend experiment process
}
// Called from Experiment-Controller class ("beyond Bochs"):
void unlockExperiment()
{
assert(m_Locked &&
"[Signal::unlockExperiment]: unlockExperiment called twice without calling lockExperiment() in between.");
m_Locked = false;
m_semBochs.post(); // resume experiment (continue bochs simulation)
}
// Called from Advice-Code ("within Bochs") to trigger event occurrence:
void signalEvent()
{
m_semContr.post(); // Signal event (to Experiment-Controller)
m_semBochs.wait(); // Wait upon handling to finish
}
// Called from Experiment-Controller to allow simulation start:
void startSimulation()
{
m_semSimCtrl.post();
}
// Called from Bochs, directly after thread creation for Experiment-Controller:
// (This ensures that Bochs waits until the experiment has been set up in the
// Experiment-Controller.)
void waitForStartup()
{
m_semSimCtrl.wait();
}
};
} // end-of-namespace: fi
#endif /* __SIGNAL_HPP__ */