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.

 

  Convenient Thread Creation
  Submitted by



CThread - Convenient thread creation.

Implements "has a thread" relationship, rather than the typical "is a thread" relationship. Pass object and member pointers or a function pointer rather than deriving from a Thread base and overriding ThreadMain. DOES NOT demonstrate error handling, portability or multithreaded programming. Dont forget multithreaded libs. The idea is to create an object to store a member pointer. Pass this object to a generic ThreadMain. Generic ThreadMain asks the object to call the member pointer. The member pointer points to the actual ThreadMain of an arbitrary class - there is no need to derive from a particular CThread. The object needs to be a templatised to accept any type of member pointer, and virtualised so that the generic ThreadMain has a single interface for all types of the templatised object. Andrew,
a_j_harvey@hotmail.com

Currently browsing [threads.zip] (1,562 bytes) - [thread.h] - (3,713 bytes)


////////////////////////////////////////////////////////////////////////////////
//
// CThread - Convenient thread creation.
//
// Implements "has a thread" relationship, rather than the typical "is a thread" relationship.
//
// Pass object and member pointers or a function pointer rather than deriving from a Thread base 
// and overriding ThreadMain.
//
// DOES NOT demonstrate error handling, portability or multithreaded programming.
//
// Dont forget multithreaded libs.
//

class CThread
{

//////////////////////////////////////////////////////////////////////////////// // // implementation // private:

struct SThreadMain { CThread* m_Thread;

SThreadMain(CThread* Thread) : m_Thread(Thread) { }

virtual ~SThreadMain() { }

virtual void Main() = 0; };

struct SFnMain : public SThreadMain { typedef void (*_F)(CThread* Thread);

_F m_Fn;

SFnMain(CThread* Thread, _F Fn) : SThreadMain(Thread), m_Fn(Fn) { }

virtual void Main() { CThread* thread = m_Thread; _F fn = m_Fn;

delete this;

// can't access members anymore (*fn)(thread); thread->Ended(); } };

template<class _C> struct SClassMain : public SThreadMain { typedef void (_C::*_M)(CThread* Thread);

_C* m_Object; _M m_Member;

SClassMain(CThread* Thread, _C* Object, _M Member) : SThreadMain(Thread), m_Object(Object), m_Member(Member) { }

virtual void Main() { CThread* thread = m_Thread; _C* object = m_Object; _M member = m_Member;

delete this;

// can't access members anymore (object->*member)(thread); thread->Ended(); } };

private:

static void ThreadMain(void* Arg) { SThreadMain* main = (SThreadMain*)Arg; main->Main(); }

private:

unsigned long m_hThread; bool m_End;

//////////////////////////////////////////////////////////////////////////////// // // constructors / destructors // public: CThread() : m_hThread(0), m_End(false) { }

private: CThread(const CThread& x);

private: CThread& operator =(const CThread& x);

public: ~CThread() { if(Active()) { RequestEnd(); Wait(); } }

//////////////////////////////////////////////////////////////////////////////// // // thread // public: void BeginThread(void (*Fn)(CThread* Thread), int StackSize = 0) { SFnMain* main = new SFnMain(this, Fn); unsigned long h_thread = _beginthread(ThreadMain, StackSize, main); m_hThread = h_thread; }

public: template<class _C> void BeginThread(_C* Object, void (_C::*Member)(CThread* Thread), int StackSize = 0) { SClassMain<_C>* main = new SClassMain<_C>(this, Object, Member); unsigned long h_thread = _beginthread(ThreadMain, StackSize, main); m_hThread = h_thread; }

public: unsigned long hThread() const { return m_hThread; }

//////////////////////////////////////////////////////////////////////////////// // // ipc // public: void Ended() { m_hThread = 0; m_End = false; }

public: void RequestEnd() { m_End = true; }

public: bool End() const { return m_End; }

public: bool Continue() const { return !End(); }

public: bool Active() const { return m_hThread != 0; }

public: void Wait(int Milli = INFINITE) const { if(Active()) { DWORD wait = WaitForSingleObject((HANDLE)m_hThread, Milli); } }

};

////////////////////////////////////////////////////////////////////////////////

Currently browsing [threads.zip] (1,562 bytes) - [main.cpp] - (1,402 bytes)


////////////////////////////////////////////////////////////////////////////////

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

#include <iostream>

#include "thread.h"

//////////////////////////////////////////////////////////////////////////////// void FnMain(CThread* Thread) { int i = 0; while(Thread->Continue()) { std::cout << "FnMain: " << i++ << std:: endl; Sleep(500); } }

//////////////////////////////////////////////////////////////////////////////// class CClassMain {

public: void ClassMain1(CThread* Thread) { int i = 0; while(Thread->Continue()) { std::cout << "ClassMain1: " << i++ << std:: endl; Sleep(510); } }

public: void ClassMain2(CThread* Thread) { int i = 0; while(Thread->Continue()) { std::cout << "ClassMain2: " << i++ << std:: endl; Sleep(520); } }

};

//////////////////////////////////////////////////////////////////////////////// void main() { CThread t1; CThread t2; CThread t3; CClassMain c;

t1.BeginThread(FnMain); t2.BeginThread(&c, &CClassMain::ClassMain1); t3.BeginThread(&c, &CClassMain::ClassMain2);

std::cin.get(); // wait for a keypress then quit }

////////////////////////////////////////////////////////////////////////////////

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.