#ifndef __SIGNAL_HPP__ #define __SIGNAL_HPP__ // FIXME: This is deprecated stuff. Delete it. #include #include #include #ifndef __puma #include #include #include #include #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 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; 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__ */