// Callbacks in C++ // Refer to http://www.cscene.org for detailed docs. // // Copyright (c) 1998 by Juergen Hermann // // To make things easy, we put all code in one file. // Large parts of this should go to thread.hpp/cpp in real real life. // Compiled using VC++ 5.0 on Windows NT 4 as a console application. #include #include #include #include #include #define WIN32_LEAN_AND_MEAN #include /////////////////////////////////////////////////////////////////////// // Utility stuff /////////////////////////////////////////////////////////////////////// inline int randrange(int lo, int hi) { return rand() / (RAND_MAX / (hi - lo + 1)) + lo; } /////////////////////////////////////////////////////////////////////// // A thread base class /////////////////////////////////////////////////////////////////////// class Thread { public: virtual ~Thread() {} void run(); unsigned long pid() const { return m_pid; } protected: Thread(); virtual void code() = 0; private: int running; unsigned long m_pid; static void dispatch(void* thread_obj); }; Thread::Thread() : running(0) , m_pid(0L) { } void Thread::run() { // Don't start two threads on the same object if (running) return; // Create an OS thread, using the static callback m_pid = _beginthread(Thread::dispatch, 0, this); running = 1; } void Thread::dispatch(void* thread_obj) { // Call the actual OO thread code ((Thread*)thread_obj)->code(); // After code() returns, kill the thread object delete (Thread*)thread_obj; } /////////////////////////////////////////////////////////////////////// // An example thread class /////////////////////////////////////////////////////////////////////// class Dice : private Thread { public: static void Dice::create(const char* dicename); static CRITICAL_SECTION sync; private: Dice(const char* dicename) : name(dicename) {} virtual void code(); std::string name; }; CRITICAL_SECTION Dice::sync; void Dice::create(const char* dicename) { (new Dice(dicename))->run(); } void Dice::code() { EnterCriticalSection(&sync); std::cout << "Started thread #" << pid() << " for " << name.c_str() << std::endl; LeaveCriticalSection(&sync); srand(time(0) * pid()); for (;;) { int val = randrange(1, 6); EnterCriticalSection(&sync); std::cout << name.c_str() << " rolled " << val << std::endl; LeaveCriticalSection(&sync); Sleep(randrange(100, 500)); // wait up to 500 ms } } /////////////////////////////////////////////////////////////////////// // Let's test! /////////////////////////////////////////////////////////////////////// int main() { InitializeCriticalSection(&Dice::sync); Dice::create("dice1"); Dice::create("dice2"); Sleep(5 * 1000L); // roll dice for 5 seconds return 0; // cleanup? what's cleanup? }