See what's going on with flipcode!




This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  Simple Win32 Thread Class
  Submitted by David Poon



I was recently faced with the task of adding support for WIN32 threads in my 3d engine. After scouring the web for ideas, I finally came up with this simple solution. Ironically the thread class that I finally wrote was inspired by Java's Thread class. I have included a zip file containing the thread class, a simple WIN32 console test program, and VC 6 workspace file.

Currently browsing [win32threads.zip] (4,786 bytes) - [threads/thread.hpp] - (3,593 bytes)

//------------------------------------------------------------------------
// File    : thread.hpp
// Author  : David Poon
// Written : 6 May 2001
// 
// WIN32 Thread class.
//
// Copyright (C) 2001 David Poon
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License 
// along with this program; if not, write to the Free Software Foundation
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//------------------------------------------------------------------------

#ifndef WIN32_THREAD_CLASS_HPP
#define WIN32_THREAD_CLASS_HPP

#include <windows.h> #include <process.h>

//------------------------------------------------------------------------ // Class : Mutex // Extends : none // // A Mutex allows threads mutually exclusive access to a resource. //------------------------------------------------------------------------ class Mutex { public: Mutex() {InitializeCriticalSection(&m_mutex);} ~Mutex() {DeleteCriticalSection(&m_mutex);}

void acquire() {EnterCriticalSection(&m_mutex);} void release() {LeaveCriticalSection(&m_mutex);}

private: CRITICAL_SECTION m_mutex; };

//------------------------------------------------------------------------ // Class : Lock // Extends : none // // A Lock provides a safe way to acquire and release a Mutex. The Mutex // is acquired when the Lock it created. The Mutex is released when the // Lock goes out of scope. //------------------------------------------------------------------------ class Lock { public: Lock(Mutex &mutex) : m_mutex(mutex) {m_mutex.acquire();} ~Lock() {m_mutex.release();}

private: Mutex &m_mutex; };

//------------------------------------------------------------------------ // Class : Win32Thread // Extends : none // // WIN32 thread class. The Win32Thread is always created in a suspended // state. The thread is not running until start() is called. If zero is // used as the stack size of the new thread, then Windows will use the // stack size of the main thread. // // To create your own thread, subclass Win32Thread and provide an // implementation for the run() method. If you want to give other threads // the ability to cleanly shutdown your thread (recommended), then your // thread's run() method should periodically call canRun() to check if // another thread has made a requested to shutdown your thread. canRun() // will return false if another thread has requested that your thread // shutdown. //------------------------------------------------------------------------ class Win32Thread { public: Win32Thread(); virtual ~Win32Thread();

bool create(unsigned int stackSize = 0); unsigned int threadId() const; void start(); void join();

void resume(); void suspend(); void shutdown(); protected: bool canRun(); virtual void run() = 0;

private: static unsigned int __stdcall threadFunc(void *args); HANDLE m_hThread; unsigned int m_threadId; volatile bool m_canRun; volatile bool m_suspended; Mutex m_mutex; };

#endif

Currently browsing [win32threads.zip] (4,786 bytes) - [threads/thread.cpp] - (2,493 bytes)

//------------------------------------------------------------------------
// File    : thread.cpp
// Author  : David Poon
// Written : 6 May 2001
// 
// Implementation file for the threading classes defined in thread.hpp
//
// Copyright (C) 2001 David Poon
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License 
// along with this program; if not, write to the Free Software Foundation
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//------------------------------------------------------------------------

#include "thread.hpp"

Win32Thread::Win32Thread() { m_hThread = 0; m_threadId = 0; m_canRun = true; m_suspended = true; }

Win32Thread::~Win32Thread() { if (m_hThread) CloseHandle(m_hThread); }

bool Win32Thread::canRun() { Lock guard(m_mutex); return m_canRun; }

bool Win32Thread::create(unsigned int stackSize) { m_hThread = reinterpret_cast<HANDLE>(_beginthreadex(0, stackSize, threadFunc, this, CREATE_SUSPENDED, &m_threadId)); if (m_hThread) return true; return false; }

void Win32Thread::join() { WaitForSingleObject(m_hThread, INFINITE); }

void Win32Thread::resume() { if (m_suspended) { Lock guard(m_mutex); if (m_suspended) { ResumeThread(m_hThread); m_suspended = false; } } }

void Win32Thread::shutdown() { if (m_canRun) { Lock guard(m_mutex);

if (m_canRun) m_canRun = false;

resume(); } }

void Win32Thread::start() { resume(); }

void Win32Thread::suspend() { if (!m_suspended) { Lock guard(m_mutex);

if (!m_suspended) { SuspendThread(m_hThread); m_suspended = true; } } }

unsigned int Win32Thread::threadId() const { return m_threadId; }

unsigned int __stdcall Win32Thread::threadFunc(void *args) { Win32Thread *pThread = reinterpret_cast<Win32Thread*>(args); if (pThread) pThread->run();

_endthreadex(0); return 0; }

Currently browsing [win32threads.zip] (4,786 bytes) - [threads/main.cpp] - (1,217 bytes)

#include <conio.h>
#include "thread.hpp"

class Display : public Win32Thread { public: Display() : Win32Thread() {} ~Display() {}

private: void run(); };

void Display::run() { while (canRun()) { Sleep(500); _putch('.'); }

_putch('*'); }

class Input : public Win32Thread { public: Input() : Win32Thread() {} ~Input() {}

private: void run(); Display m_display; };

void Input::run() { // Start the Display thread. if (m_display.create()) m_display.start(); else return;

bool quit = false;

while (!quit) { if (_kbhit()) { switch (_getch()) { default: break;

// Suspend Display thread case 's': case 'S': m_display.suspend(); break;

// Resume Display thread case 'r': case 'R': m_display.resume(); break;

// Shutdown Input and Display threads. case 'q': case 'Q': case 27: m_display.shutdown(); m_display.join(); quit = true; break; } } } }

int main() { Input input;

if (input.create()) { input.start(); input.join(); }

_cputs("\r\nmain thread has now joined with input thread\r\n"); return 0; }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

 

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.