/*
* Thread that support cross platform and support global and local start routine, and support
* Windows api and C Run-Time Library(even extension) on windows.
* <p>
* To implements a simple thread, only to overrides the run method.
*
* @author ada
* @version 1.0
* @since 1.0
*/
#include <windows.h>
#if defined(_WIN32) && defined(_MT)
#include <process.h>
#endif
#include "Runnable.hpp"
#if ! defined THREAD
#define THREAD
// GLOBAL_START_ROUTINE is a user defined macro, likes a switch, to determine whether to
// select global thread start routine or not. GLOBAL_START_ROUTINE can be defined in program,
// or using compiler preprocessor options(PREPROCESSOR) /D to define user defined macro
// GLOBAL_START_ROUTINE to compiles global start routine edition of Thread
#if defined GLOBAL_START_ROUTINE
#define _GLOBAL_START_ROUTINE
#pragma message ("GLOBAL_START_ROUTINE defined, using global thread start routine.")
// windows
#ifdef _WIN32
// using compiler linking options /MT to compiles C Run-Time Library(_beginthread, _beginthreadex)
// edition of Thread
#if defined(_MT) && (! defined(_MT_RT_EX))
#pragma message ("Using C Run-Time Library global thread start routine.")
//#error "C Run-Time Library global thread start routine not supported."
void execute(void *args);
typedef void (* LP_CRT_THREAD_START_ROUTINE)(void *args);
#elif defined(_MT) && defined(_MT_RT_EX)
#pragma message ("Using C Run-Time Library extension global thread start routine.")
//#error "C Run-Time Library extension global thread start routine not supported."
unsigned __stdcall execute(void *args);
typedef unsigned (__stdcall * LP_CRT_EX_THREAD_START_ROUTINE)(void *args);
#else
DWORD execute(LPVOID args);
#endif
// linux
#else
void* execute(void *args);
#endif
// User defined macro GLOBAL_START_ROUTINE is not specific
// Compiles global start routine edition of Thread using compiler preprocessor options(PREPROCESSOR) /D
// to define user defined macro GLOBAL_START_ROUTINE
#else
#pragma message ("GLOBAL_START_ROUTINE not defined, do not using global thread start routine.")
// If GLOBAL_START_ROUTINE not defined, for thread start routine function details, See Thread class
// declaration when user defined macro defined
#endif
/**
*
*
*
*/
class /*TK_API*/ Thread : public Runnable
{
private:
#if defined(_WIN32) && defined(_MT)
#ifdef _MT_RT_EX
unsigned threadID;
#else
unsigned long threadID;
#endif
#else
DWORD threadID;
#endif
Runnable *target;
public:
Thread();
Thread(const Runnable *runnable);
#if ! defined _GLOBAL_START_ROUTINE
// windows
#ifdef _WIN32
#if defined(_MT) && (! defined(_MT_RT_EX))
#pragma message ("Using C Run-Time Library global thread start routine.")
#error "C Run-Time Library global thread start routine not supported."
#elif defined(_MT) && defined(_MT_RT_EX)
#pragma message ("Using C Run-Time Library extension global thread start routine.")
#error "C Run-Time Library extension global thread start routine not supported."
#else
static DWORD execute(LPVOID args);
#endif
// linux
#else
static void* execute(void *args);
#endif
#endif
void start();
virtual void run();
};
#endif
======================================================================
/*
*
*
* @AUTHOR ADA
* @VERSION 1.0
* @SINCE 1.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <windows.h>
#include <log.h>
#include "Thread.hpp"
//#define _MT
using namespace std;
#if ! defined _GLOBAL_START_ROUTINE
DWORD Thread::execute(LPVOID args)
{
Thread* t = (Thread *) args;
t->run();
return 1;
}
#else
#if defined(_MT) && (! defined(_MT_RT_EX))
void execute(void *args)
{
debug("start routine defined(_MT) && (! defined(_MT_RT_EX))");
Thread* t = (Thread *) args;
t->run();
}
#elif defined(_MT) && defined(_MT_RT_EX)
unsigned __stdcall execute(void *args)
{
debug("start routine defined(_MT) && defined(_MT_RT_EX)");
Thread* t = (Thread *) args;
t->run();
return 0;
}
#else
DWORD execute(LPVOID args)
{
Thread* t = (Thread *) args;
t->run();
return 1;
}
#endif
#endif
/**
*
*
*
*/
Thread::Thread()
{
this->threadID = 0;
this->target = NULL;
}
Thread::Thread(const Runnable *runnable)
{
this->threadID = 0;
this->target = (Runnable *) runnable;
}
void Thread::start()
{
#if defined(_MT) && (! defined(_MT_RT_EX))
#ifndef _GLOBAL_START_ROUTINE
LP_CRT_THREAD_START_ROUTINE startRoutine = (LP_CRT_THREAD_START_ROUTINE) Thread::execute;
printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n");
#else
LP_CRT_THREAD_START_ROUTINE startRoutine = (LP_CRT_THREAD_START_ROUTINE) execute;
printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n");
#endif
#elif defined(_MT) && defined(_MT_RT_EX)
#ifndef _GLOBAL_START_ROUTINE
LP_CRT_EX_THREAD_START_ROUTINE startRoutine = (LP_CRT_EX_THREAD_START_ROUTINE) Thread::execute;
printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n");
#else
LP_CRT_EX_THREAD_START_ROUTINE startRoutine = (LP_CRT_EX_THREAD_START_ROUTINE) execute;
printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n");
#endif
#else
#ifndef _GLOBAL_START_ROUTINE
LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) Thread::execute;
printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n");
#else
LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) execute;
printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n");
#endif
#endif
#if defined(_MT) && (! defined(_MT_RT_EX))
debug("begin thread through _beginthread()");
threadID = _beginthread(startRoutine,
0,
(void *) this);
#elif defined(_MT) && defined(_MT_RT_EX)
debug("begin thread through _beginthreadex()");
threadID = _beginthreadex(NULL, 0, startRoutine, (void *) this, 0, &(this->threadID));
#else
::CreateThread(NULL, 0, startRoutine, (LPVOID) this, 0, &(this->threadID));
#endif
debug("Thread %d started", this->threadID);
}
void Thread::run()
{
if (target != NULL)
{
target->run();
}
else
{
debug("Thread::run()");
}
}