mirror of
https://github.com/SWG-Source/src.git
synced 2026-08-01 01:16:03 -04:00
Added sharedThread library
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(sharedThread)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public)
|
||||
|
||||
add_subdirectory(src)
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/FirstSharedThread.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/RunThread.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/SetupSharedThread.h"
|
||||
@@ -0,0 +1,7 @@
|
||||
#if defined(PLATFORM_WIN32)
|
||||
#include "../../src/win32/Thread.h"
|
||||
#elif defined(PLATFORM_LINUX)
|
||||
#include "../../src/linux/Thread.h"
|
||||
#else
|
||||
#error unsupported platform
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/ThreadHandle.h"
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
set(SHARED_SOURCES
|
||||
shared/FirstSharedThread.h
|
||||
shared/RunThread.cpp
|
||||
shared/RunThread.h
|
||||
shared/SetupSharedThread.cpp
|
||||
shared/SetupSharedThread.h
|
||||
shared/ThreadHandle.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM_SOURCES
|
||||
win32/FirstSharedThread.cpp
|
||||
win32/Thread.cpp
|
||||
win32/Thread.h
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
|
||||
else()
|
||||
set(PLATFORM_SOURCES
|
||||
linux/Thread.cpp
|
||||
linux/Thread.h
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/linux)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shared
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSynchronization/include/public
|
||||
)
|
||||
|
||||
add_library(sharedThread STATIC
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
@@ -0,0 +1,159 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Thread.cpp
|
||||
// Acy Stapp
|
||||
//
|
||||
// Copyright 6/19/2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedThread/Thread.h"
|
||||
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedFoundation/PerThreadData.h"
|
||||
#include <cstdio>
|
||||
|
||||
class MainThread: public Thread
|
||||
{
|
||||
public:
|
||||
MainThread(const std::string &name): Thread(name) {}
|
||||
protected:
|
||||
void run() {}
|
||||
private:
|
||||
MainThread(const MainThread &o);
|
||||
MainThread &operator =(const MainThread &o);
|
||||
};
|
||||
|
||||
pthread_key_t Thread::implindex;
|
||||
Thread * Thread::mainThread;
|
||||
|
||||
void Thread::install()
|
||||
{
|
||||
DEBUG_FATAL(mainThread, ("Thread::install: already installed"));
|
||||
ExitChain::add(remove, "Thread::remove");
|
||||
|
||||
pthread_key_create(&implindex, 0);
|
||||
mainThread = new MainThread("Main");
|
||||
mainThread->attach();
|
||||
}
|
||||
|
||||
void Thread::remove()
|
||||
{
|
||||
DEBUG_FATAL(!mainThread, ("Thread::remove: not installed"));
|
||||
DEBUG_FATAL(mainThread->refcount > 1, ("Someone still holds the main thread"));
|
||||
delete mainThread;
|
||||
pthread_key_delete(implindex);
|
||||
|
||||
mainThread = 0;
|
||||
}
|
||||
|
||||
Thread::Thread(const std::string &i_name)
|
||||
: refcount(1), name(i_name)
|
||||
{
|
||||
doneFlag = false;
|
||||
}
|
||||
|
||||
void Thread::start()
|
||||
{
|
||||
pthread_create(&thread, 0, threadFunc, this);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
}
|
||||
|
||||
void Thread::attach()
|
||||
{
|
||||
thread = pthread_self();
|
||||
pthread_setspecific(implindex, this);
|
||||
}
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
pthread_detach(thread);
|
||||
}
|
||||
|
||||
void * Thread::threadFunc(void * i)
|
||||
{
|
||||
Thread * impl = static_cast<Thread *>(i);
|
||||
pthread_setspecific(implindex, impl);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
Os::setThreadName(impl->thread, impl->name.c_str());
|
||||
PerThreadData::threadInstall(true);
|
||||
impl->run();
|
||||
PerThreadData::threadRemove();
|
||||
impl->kill();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Thread::kill()
|
||||
{
|
||||
int t = getCurrentThread()->thread;
|
||||
doneFlag = true;
|
||||
deref();
|
||||
if (this == getCurrentThread())
|
||||
{
|
||||
pthread_exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_cancel(t);
|
||||
}
|
||||
}
|
||||
|
||||
bool Thread::done()
|
||||
{
|
||||
return doneFlag;
|
||||
}
|
||||
|
||||
void Thread::wait()
|
||||
{
|
||||
if (!doneFlag)
|
||||
{
|
||||
void * junk;
|
||||
pthread_join(thread, &junk);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int interpPriority(float t, int policy)
|
||||
{
|
||||
return (int)(sched_get_priority_max(policy)*t + sched_get_priority_min(policy)*(1-t));
|
||||
}
|
||||
|
||||
void Thread::setPriority(ePriority priority)
|
||||
{
|
||||
static int policies[] =
|
||||
{
|
||||
SCHED_OTHER,
|
||||
SCHED_OTHER,
|
||||
SCHED_OTHER,
|
||||
SCHED_OTHER,
|
||||
SCHED_FIFO
|
||||
};
|
||||
static int priorities[] =
|
||||
{
|
||||
interpPriority(0.0, SCHED_OTHER),
|
||||
interpPriority(0.25, SCHED_OTHER),
|
||||
interpPriority(0.5, SCHED_OTHER),
|
||||
interpPriority(0.75, SCHED_OTHER),
|
||||
interpPriority(0.75, SCHED_FIFO)
|
||||
};
|
||||
sched_param p;
|
||||
p.sched_priority = priorities[priority];
|
||||
pthread_setschedparam(thread, policies[priority], &p);
|
||||
}
|
||||
|
||||
// Make sure the header-only files compile :)
|
||||
|
||||
#if 0
|
||||
|
||||
#include "sharedSynchronization/CountingSemaphore.h"
|
||||
#include "sharedSynchronization/BlockingPointer.h"
|
||||
#include "sharedSynchronization/BlockingQueue.h"
|
||||
#include "sharedSynchronization/WriteOnce.h"
|
||||
|
||||
Mutex t;
|
||||
BlockingQueue<int> bqint(t, 0, 0);
|
||||
BlockingPointer<int> bpint(t, 0, 0);
|
||||
WriteOnce<int> woint;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,100 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Thread.h
|
||||
// Acy Stapp
|
||||
//
|
||||
// Copyright 6/19/2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_Thread_h
|
||||
#define INCLUDED_Thread_h
|
||||
|
||||
#include "sharedSynchronization/InterlockedInteger.h"
|
||||
#include <string>
|
||||
|
||||
class Thread
|
||||
{
|
||||
template <class T> friend class TypedThreadHandle;
|
||||
public:
|
||||
static void install();
|
||||
static void remove();
|
||||
|
||||
Thread(const std::string &i_name=std::string());
|
||||
|
||||
void kill();
|
||||
bool done();
|
||||
void wait();
|
||||
|
||||
enum ePriority
|
||||
{
|
||||
kIdle = 0,
|
||||
kLow = 1,
|
||||
kNormal = 2,
|
||||
kHigh = 3,
|
||||
kCritical = 4
|
||||
};
|
||||
void setPriority(ePriority priority);
|
||||
|
||||
const std::string &getName() const;
|
||||
void setName(const std::string &i_name);
|
||||
|
||||
static Thread * getCurrentThread();
|
||||
static Thread * getMainThread();
|
||||
protected:
|
||||
virtual ~Thread();
|
||||
virtual void run()=0;
|
||||
|
||||
pthread_t thread;
|
||||
|
||||
InterlockedInteger refcount;
|
||||
private:
|
||||
Thread(const Thread &o);
|
||||
Thread &operator =(const Thread &o);
|
||||
|
||||
void start();
|
||||
void attach(); // pick up the currently running thread
|
||||
|
||||
void ref();
|
||||
void deref();
|
||||
|
||||
bool doneFlag;
|
||||
|
||||
std::string name;
|
||||
|
||||
static pthread_key_t implindex;
|
||||
static Thread * mainThread;
|
||||
static void * threadFunc(void * data);
|
||||
};
|
||||
|
||||
inline void Thread::ref()
|
||||
{
|
||||
++refcount;
|
||||
}
|
||||
|
||||
inline void Thread::deref()
|
||||
{
|
||||
if (--refcount == 0) delete this;
|
||||
}
|
||||
|
||||
inline Thread * Thread::getCurrentThread()
|
||||
{
|
||||
return static_cast<Thread *>(pthread_getspecific(implindex));
|
||||
}
|
||||
|
||||
inline Thread * Thread::getMainThread()
|
||||
{
|
||||
return mainThread;
|
||||
}
|
||||
|
||||
inline const std::string &Thread::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
inline void Thread::setName(const std::string &i_name)
|
||||
{
|
||||
name = i_name;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstThread.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_FirstThread_H
|
||||
#define INCLUDED_FirstThread_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// runThread.cpp
|
||||
// Acy Stapp
|
||||
//
|
||||
// Copyright 6/19/2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedThread/FirstSharedThread.h"
|
||||
#include "sharedThread/RunThread.h"
|
||||
|
||||
FuncPtrThreadZero::Handle runThread(void (* func)())
|
||||
{
|
||||
return TypedThreadHandle<FuncPtrThreadZero> (new FuncPtrThreadZero(func));
|
||||
}
|
||||
|
||||
FuncPtrThreadZero::Handle runNamedThread(const std::string &name, void (* func)())
|
||||
{
|
||||
return TypedThreadHandle<FuncPtrThreadZero> (new FuncPtrThreadZero(name, func));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Testing stuff
|
||||
|
||||
class testclass
|
||||
{
|
||||
public:
|
||||
void zeroArg() {}
|
||||
void oneArg(testclass *) {}
|
||||
void twoArg(testclass *, int) {}
|
||||
};
|
||||
|
||||
testclass m;
|
||||
|
||||
typedef MemberFunctionThreadZero<testclass>::Handle AsyncTestMemberFunctionZero;
|
||||
AsyncTestMemberFunctionZero temp = runThread(m, testclass::zeroArg);
|
||||
|
||||
typedef MemberFunctionThreadOne<testclass, testclass *>::Handle AsyncTestMemberFunctionOne;
|
||||
AsyncTestMemberFunctionOne temp2 = runThread(m, testclass::oneArg, &m);
|
||||
|
||||
typedef MemberFunctionThreadTwo<testclass, testclass *, int>::Handle AsyncTestMemberFunctionTwo;
|
||||
AsyncTestMemberFunctionTwo temp3 = runThread(m, testclass::twoArg, &m, 4);
|
||||
#endif
|
||||
@@ -0,0 +1,201 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// runThread.h
|
||||
// Acy Stapp
|
||||
//
|
||||
// Copyright 6/19/2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_runThread_h
|
||||
#define INCLUDED_runThread_h
|
||||
|
||||
#include "sharedThread/ThreadHandle.h"
|
||||
#include "sharedThread/Thread.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
// Thread starters
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
template <class CLASS>
|
||||
class MemberFunctionThreadZero: public Thread
|
||||
{
|
||||
public:
|
||||
typedef void (CLASS::* FUNCTION)(void);
|
||||
typedef TypedThreadHandle<MemberFunctionThreadZero<CLASS> > Handle;
|
||||
|
||||
MemberFunctionThreadZero(CLASS &i_object, FUNCTION i_func): Thread(), object(i_object), func(i_func) {}
|
||||
MemberFunctionThreadZero(const std::string &i_name, CLASS &i_object, FUNCTION i_func): Thread(i_name), object(i_object), func(i_func) {}
|
||||
private:
|
||||
MemberFunctionThreadZero(const MemberFunctionThreadZero &o);
|
||||
MemberFunctionThreadZero &operator =(const MemberFunctionThreadZero &o);
|
||||
|
||||
void run() { (object.*func)(); }
|
||||
CLASS &object;
|
||||
FUNCTION func;
|
||||
};
|
||||
|
||||
template <class CLASS>
|
||||
typename MemberFunctionThreadZero<CLASS>::Handle runThread(CLASS &o, typename MemberFunctionThreadZero<CLASS>::FUNCTION function)
|
||||
{
|
||||
return TypedThreadHandle<MemberFunctionThreadZero<CLASS> > (new MemberFunctionThreadZero<CLASS>(o, function));
|
||||
}
|
||||
|
||||
template <class CLASS>
|
||||
TypedThreadHandle<MemberFunctionThreadZero<CLASS> > runNamedThread(const std::string &name, CLASS &o, typename MemberFunctionThreadZero<CLASS>::FUNCTION function)
|
||||
{
|
||||
return TypedThreadHandle<MemberFunctionThreadZero<CLASS> > (new MemberFunctionThreadZero<CLASS>(name, o, function));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
template <class CLASS, class ARG1>
|
||||
class MemberFunctionThreadOne: public Thread
|
||||
{
|
||||
public:
|
||||
typedef void (CLASS::* FUNCTION)(ARG1 o);
|
||||
typedef TypedThreadHandle<MemberFunctionThreadOne<CLASS, ARG1> > Handle;
|
||||
|
||||
MemberFunctionThreadOne(CLASS &i_object, FUNCTION i_func, ARG1 i_arg1): Thread(), object(i_object), func(i_func), arg1(i_arg1) {}
|
||||
MemberFunctionThreadOne(const std::string &i_name, CLASS &i_object, FUNCTION i_func, ARG1 i_arg1): Thread(i_name), object(i_object), func(i_func), arg1(i_arg1) {}
|
||||
private:
|
||||
MemberFunctionThreadOne(const MemberFunctionThreadOne &o);
|
||||
MemberFunctionThreadOne &operator =(const MemberFunctionThreadOne &o);
|
||||
|
||||
void run() { (object.*func)(arg1); }
|
||||
CLASS &object;
|
||||
FUNCTION func;
|
||||
ARG1 arg1;
|
||||
};
|
||||
|
||||
template <class CLASS, class ARG1>
|
||||
TypedThreadHandle<MemberFunctionThreadOne<CLASS, ARG1> > runThread(CLASS &o, void (CLASS::* function)(ARG1 o), ARG1 arg1)
|
||||
{
|
||||
return TypedThreadHandle<MemberFunctionThreadOne<CLASS, ARG1> > (new MemberFunctionThreadOne<CLASS, ARG1>(o, function, arg1));
|
||||
}
|
||||
|
||||
template <class CLASS, class ARG1>
|
||||
TypedThreadHandle<MemberFunctionThreadOne<CLASS, ARG1> > runNamedThread(const std::string &name, CLASS &o, void (CLASS::* function)(ARG1 o), ARG1 arg1)
|
||||
{
|
||||
return TypedThreadHandle<MemberFunctionThreadOne<CLASS, ARG1> > (new MemberFunctionThreadOne<CLASS, ARG1>(name, o, function, arg1));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
|
||||
template <class CLASS, class ARG1, class ARG2>
|
||||
class MemberFunctionThreadTwo: public Thread
|
||||
{
|
||||
public:
|
||||
typedef void (CLASS::* FUNCTION)(ARG1 o, ARG2 p);
|
||||
typedef TypedThreadHandle<MemberFunctionThreadTwo<CLASS, ARG1, ARG2> > Handle;
|
||||
|
||||
MemberFunctionThreadTwo(CLASS &i_object, FUNCTION i_func, ARG1 i_arg1, ARG2 i_arg2): Thread(), object(i_object), func(i_func), arg1(i_arg1), arg2(i_arg2) {}
|
||||
MemberFunctionThreadTwo(const std::string &i_name, CLASS &i_object, FUNCTION i_func, ARG1 i_arg1, ARG2 i_arg2): Thread(i_name), object(i_object), func(i_func), arg1(i_arg1), arg2(i_arg2) {}
|
||||
private:
|
||||
MemberFunctionThreadTwo(const MemberFunctionThreadTwo &o);
|
||||
MemberFunctionThreadTwo &operator =(const MemberFunctionThreadTwo &o);
|
||||
|
||||
void run() { (object.*func)(arg1, arg2); }
|
||||
CLASS &object;
|
||||
FUNCTION func;
|
||||
ARG1 arg1;
|
||||
ARG2 arg2;
|
||||
};
|
||||
|
||||
template <class CLASS, class ARG1, class ARG2>
|
||||
TypedThreadHandle<MemberFunctionThreadTwo<CLASS, ARG1, ARG2> > runThread(CLASS &o, void (CLASS::* function)(ARG1 o, ARG2 p), ARG1 arg1, ARG2 arg2)
|
||||
{
|
||||
return TypedThreadHandle<MemberFunctionThreadTwo<CLASS, ARG1, ARG2> > (new MemberFunctionThreadTwo<CLASS, ARG1, ARG2>(o, function, arg1, arg2));
|
||||
}
|
||||
|
||||
template <class CLASS, class ARG1, class ARG2>
|
||||
TypedThreadHandle<MemberFunctionThreadTwo<CLASS, ARG1, ARG2> > runNamedThread(const std::string &name, CLASS &o, void (CLASS::* function)(ARG1 o, ARG2 p), ARG1 arg1, ARG2 arg2)
|
||||
{
|
||||
return TypedThreadHandle<MemberFunctionThreadTwo<CLASS, ARG1, ARG2> > (new MemberFunctionThreadTwo<CLASS, ARG1, ARG2>(name, o, function, arg1, arg2));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class FuncPtrThreadZero: public Thread
|
||||
{
|
||||
public:
|
||||
typedef void (* FUNCTION)();
|
||||
typedef TypedThreadHandle<FuncPtrThreadZero> Handle;
|
||||
|
||||
explicit FuncPtrThreadZero(void (* i_func)()): Thread(), function(i_func) {}
|
||||
FuncPtrThreadZero(const std::string &i_name, void (* i_func)()): Thread(i_name), function(i_func) {}
|
||||
private:
|
||||
FuncPtrThreadZero();
|
||||
FuncPtrThreadZero(const FuncPtrThreadZero &o);
|
||||
FuncPtrThreadZero &operator =(const FuncPtrThreadZero &o);
|
||||
void run() { function(); }
|
||||
FUNCTION function;
|
||||
};
|
||||
|
||||
TypedThreadHandle<FuncPtrThreadZero> runThread(FuncPtrThreadZero::FUNCTION func);
|
||||
TypedThreadHandle<FuncPtrThreadZero> runNamedThread(const std::string &name, FuncPtrThreadZero::FUNCTION func);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <class ARG1>
|
||||
class FuncPtrThreadOne: public Thread
|
||||
{
|
||||
public:
|
||||
typedef void (* FUNCTION)(ARG1 arg1);
|
||||
typedef TypedThreadHandle<FuncPtrThreadOne<ARG1> > Handle;
|
||||
|
||||
FuncPtrThreadOne(FUNCTION i_func, ARG1 i_arg1): Thread(), function(i_func), arg1(i_arg1) {}
|
||||
FuncPtrThreadOne(const std::string &i_name, FUNCTION i_func, ARG1 i_arg1): Thread(i_name), function(i_func), arg1(i_arg1) {}
|
||||
private:
|
||||
FuncPtrThreadOne(const FuncPtrThreadOne &o);
|
||||
FuncPtrThreadOne &operator =(const FuncPtrThreadOne &o);
|
||||
void run() { function(arg1); }
|
||||
FUNCTION function;
|
||||
ARG1 arg1;
|
||||
};
|
||||
|
||||
template <class ARG1>
|
||||
TypedThreadHandle<FuncPtrThreadOne<ARG1> > runThread(typename FuncPtrThreadOne<ARG1>::FUNCTION func, ARG1 arg1)
|
||||
{
|
||||
return TypedThreadHandle<FuncPtrThreadOne<ARG1> > (new FuncPtrThreadOne<ARG1>(func, arg1));
|
||||
}
|
||||
|
||||
template <class ARG1>
|
||||
TypedThreadHandle<FuncPtrThreadOne<ARG1> > runNamedThread(const std::string &name, typename FuncPtrThreadOne<ARG1>::FUNCTION func, ARG1 arg1)
|
||||
{
|
||||
return TypedThreadHandle<FuncPtrThreadOne<ARG1> > (new FuncPtrThreadOne<ARG1>(name, func, arg1));
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
template <class ARG1, class ARG2>
|
||||
class FuncPtrThreadTwo: public Thread
|
||||
{
|
||||
public:
|
||||
typedef void (* FUNCTION)(ARG1, ARG2);
|
||||
typedef TypedThreadHandle<FuncPtrThreadTwo<ARG1,ARG2> > Handle;
|
||||
|
||||
FuncPtrThreadTwo(FUNCTION i_func, ARG1 i_arg1, ARG2 i_arg2): Thread(), function(i_func), arg1(i_arg1), arg2(i_arg2) {}
|
||||
FuncPtrThreadTwo(const std::string &i_name, FUNCTION i_func, ARG1 i_arg1, ARG2 i_arg2): Thread(i_name), function(i_func), arg1(i_arg1), arg2(i_arg2) {}
|
||||
private:
|
||||
FuncPtrThreadTwo(const FuncPtrThreadTwo &o);
|
||||
FuncPtrThreadTwo &operator =(const FuncPtrThreadTwo &o);
|
||||
void run() { function(arg1, arg2); }
|
||||
FUNCTION function;
|
||||
ARG1 arg1;
|
||||
ARG2 arg2;
|
||||
};
|
||||
|
||||
template <class ARG1, class ARG2>
|
||||
TypedThreadHandle<FuncPtrThreadTwo<ARG1,ARG2> > runThread(typename FuncPtrThreadTwo<ARG1,ARG2>::FUNCTION func, ARG1 arg1, ARG2 arg2)
|
||||
{
|
||||
return TypedThreadHandle<FuncPtrThreadTwo<ARG1,ARG2> > (new FuncPtrThreadTwo<ARG1,ARG2>(func, arg1, arg2));
|
||||
}
|
||||
|
||||
template <class ARG1, class ARG2>
|
||||
TypedThreadHandle<FuncPtrThreadTwo<ARG1,ARG2> > runNamedThread(const std::string &name, typename FuncPtrThreadTwo<ARG1,ARG2>::FUNCTION func, ARG1 arg1, ARG2 arg2)
|
||||
{
|
||||
return TypedThreadHandle<FuncPtrThreadTwo<ARG1,ARG2> > (new FuncPtrThreadTwo<ARG1,ARG2>(name, func, arg1, arg2));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// SetupSharedThread.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedThread/FirstSharedThread.h"
|
||||
#include "sharedThread/SetupSharedThread.h"
|
||||
|
||||
#include "sharedFoundation/PerThreadData.h"
|
||||
#include "sharedThread/Thread.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void SetupSharedThread::install()
|
||||
{
|
||||
// and the per-thread-data is used early on
|
||||
PerThreadData::install();
|
||||
|
||||
// Install the thread support stuff
|
||||
Thread::install();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void SetupSharedThread::remove()
|
||||
{
|
||||
// and the per-thread-data is used early on
|
||||
PerThreadData::remove();
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,28 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// SetupSharedThread.h
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_SetupSharedThread_H
|
||||
#define INCLUDED_SetupSharedThread_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class SetupSharedThread
|
||||
{
|
||||
public:
|
||||
|
||||
static void install();
|
||||
static void remove();
|
||||
|
||||
private:
|
||||
SetupSharedThread();
|
||||
SetupSharedThread(const SetupSharedThread &);
|
||||
SetupSharedThread &operator =(const SetupSharedThread &);
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ThreadHandle.h
|
||||
// Acy Stapp
|
||||
//
|
||||
// Copyright 6/19/2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_ThreadHandle_h
|
||||
#define INCLUDED_ThreadHandle_h
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedThread/Thread.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
template <class T>
|
||||
class TypedThreadHandle
|
||||
{
|
||||
public:
|
||||
typedef TypedThreadHandle<Thread> ThreadHandle;
|
||||
|
||||
TypedThreadHandle();
|
||||
~TypedThreadHandle();
|
||||
explicit TypedThreadHandle(T * i);
|
||||
TypedThreadHandle(const TypedThreadHandle<T> &o);
|
||||
|
||||
template <class O>
|
||||
TypedThreadHandle<T> &operator =(const TypedThreadHandle<O> &o)
|
||||
{
|
||||
O * oimpl = o.getImpl();
|
||||
if (impl != oimpl)
|
||||
{
|
||||
if (oimpl)
|
||||
oimpl->ref();
|
||||
if (impl)
|
||||
impl->deref();
|
||||
impl = oimpl;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() const { return !(impl == 0); } //lint !e1930 conversion operator found
|
||||
bool operator !() const { return impl == 0; }
|
||||
void zero();
|
||||
void waitZero(); // wait then zero
|
||||
|
||||
Thread * operator ->() { return impl; }
|
||||
const Thread * operator ->() const { return impl; }
|
||||
|
||||
static ThreadHandle getCurrentThread();
|
||||
static ThreadHandle getMainThread();
|
||||
// TODO AJS - this is not needed once we get proper template friend declarations - friend template<class O> class TypedThreadHandle<O>;
|
||||
T * getImpl() const { return const_cast<T *>(impl); }
|
||||
protected:
|
||||
T * impl;
|
||||
};
|
||||
|
||||
typedef TypedThreadHandle<Thread> ThreadHandle;
|
||||
|
||||
template <class T>
|
||||
TypedThreadHandle<T>::TypedThreadHandle()
|
||||
: impl(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
TypedThreadHandle<T>::TypedThreadHandle(T * i)
|
||||
: impl(i)
|
||||
{
|
||||
if (impl)
|
||||
{
|
||||
impl->ref();
|
||||
impl->start();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
TypedThreadHandle<T>::TypedThreadHandle(const TypedThreadHandle &o)
|
||||
: impl(o.impl)
|
||||
{
|
||||
if (impl)
|
||||
impl->ref();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
TypedThreadHandle<T>::~TypedThreadHandle()
|
||||
{
|
||||
if (impl)
|
||||
impl->deref();
|
||||
impl = 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
TypedThreadHandle<Thread> TypedThreadHandle<T>::getCurrentThread()
|
||||
{
|
||||
return TypedThreadHandle<Thread>(Thread::getCurrentThread());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
TypedThreadHandle<Thread> TypedThreadHandle<T>::getMainThread()
|
||||
{
|
||||
return TypedThreadHandle<Thread>(Thread::getMainThread());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void TypedThreadHandle<T>::waitZero()
|
||||
{
|
||||
if (impl)
|
||||
{
|
||||
impl->wait();
|
||||
impl->deref();
|
||||
}
|
||||
impl = 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void TypedThreadHandle<T>::zero()
|
||||
{
|
||||
if (impl)
|
||||
impl->deref();
|
||||
impl = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstThread.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedThread/FirstSharedThread.h"
|
||||
@@ -0,0 +1,179 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Thread.cpp
|
||||
// Acy Stapp
|
||||
//
|
||||
// Copyright6/19/2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedThread/FirstSharedThread.h"
|
||||
#include "sharedThread/Thread.h"
|
||||
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedSynchronization/Mutex.h"
|
||||
#include "sharedSynchronization/RecursiveMutex.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedFoundation/PerThreadData.h"
|
||||
#include <process.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
class MainThread: public Thread
|
||||
{
|
||||
public:
|
||||
MainThread(const std::string &name): Thread(name) {}
|
||||
protected:
|
||||
void run() {}
|
||||
private:
|
||||
MainThread(const MainThread &o);
|
||||
MainThread &operator =(const MainThread &o);
|
||||
};
|
||||
|
||||
int Thread::implindex;
|
||||
Thread * Thread::mainThread;
|
||||
|
||||
void Thread::install()
|
||||
{
|
||||
DEBUG_FATAL(mainThread, ("Thread::install: already installed"));
|
||||
|
||||
implindex = TlsAlloc();
|
||||
mainThread = new MainThread("Main");
|
||||
mainThread->attach();
|
||||
|
||||
ExitChain::add(remove, "Thread::remove");
|
||||
|
||||
Mutex::install();
|
||||
RecursiveMutex::install();
|
||||
|
||||
}
|
||||
|
||||
void Thread::remove()
|
||||
{
|
||||
DEBUG_FATAL(!mainThread, ("Thread::remove: not installed"));
|
||||
DEBUG_FATAL(mainThread->refcount > 1, ("Someone still holds the main thread"));
|
||||
delete mainThread; // can't kill because it would terminate the app
|
||||
TlsFree(implindex);
|
||||
|
||||
Mutex::remove();
|
||||
RecursiveMutex::remove();
|
||||
|
||||
mainThread = 0;
|
||||
}
|
||||
|
||||
Thread::Thread()
|
||||
: refcount(1), name(new std::string)
|
||||
{
|
||||
}
|
||||
|
||||
Thread::Thread(const std::string &i_name)
|
||||
: refcount(1), name(new std::string(i_name))
|
||||
{
|
||||
}
|
||||
|
||||
void Thread::start()
|
||||
{
|
||||
handle = (HANDLE) _beginthreadex(0, 0, threadFunc, this, 0, &id);
|
||||
}
|
||||
|
||||
void Thread::attach()
|
||||
{
|
||||
id = GetCurrentThreadId();
|
||||
HANDLE process = GetCurrentProcess();
|
||||
DuplicateHandle(process, GetCurrentThread(), process, &handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||
|
||||
TlsSetValue(implindex, this);
|
||||
Os::setThreadName(id, name->c_str());
|
||||
}
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
CloseHandle(handle);
|
||||
delete name;
|
||||
}
|
||||
|
||||
unsigned int Thread::threadFunc(void * i)
|
||||
{
|
||||
Thread * impl = static_cast<Thread *>(i);
|
||||
TlsSetValue(implindex, impl);
|
||||
Os::setThreadName(impl->id, impl->name->c_str());
|
||||
PerThreadData::threadInstall(true);
|
||||
impl->run();
|
||||
PerThreadData::threadRemove();
|
||||
impl->kill();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Thread::kill()
|
||||
{
|
||||
void * h = getCurrentThread()->handle;
|
||||
deref();
|
||||
if (this == getCurrentThread())
|
||||
{
|
||||
_endthreadex(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
TerminateThread(h, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::wait()
|
||||
{
|
||||
WaitForSingleObject(handle, INFINITE);
|
||||
}
|
||||
|
||||
bool Thread::done()
|
||||
{
|
||||
return WaitForSingleObject(handle, 0) == WAIT_OBJECT_0; // WAIT_TIMEOUT if the thread is still active
|
||||
}
|
||||
|
||||
void Thread::setName(const std::string &i_name)
|
||||
{
|
||||
*name = i_name;
|
||||
Os::setThreadName(id, name->c_str());
|
||||
}
|
||||
|
||||
void Thread::setPriority(ePriority priority)
|
||||
{
|
||||
static int priorities[] =
|
||||
{
|
||||
THREAD_PRIORITY_IDLE,
|
||||
THREAD_PRIORITY_LOWEST,
|
||||
THREAD_PRIORITY_NORMAL,
|
||||
THREAD_PRIORITY_HIGHEST,
|
||||
THREAD_PRIORITY_TIME_CRITICAL
|
||||
};
|
||||
::SetThreadPriority(handle, priorities[priority]);
|
||||
}
|
||||
|
||||
void Thread::suspend()
|
||||
{
|
||||
::SuspendThread(handle);
|
||||
}
|
||||
|
||||
void Thread::resume()
|
||||
{
|
||||
::ResumeThread(handle);
|
||||
}
|
||||
|
||||
const std::string &Thread::getName() const
|
||||
{
|
||||
return *name;
|
||||
}
|
||||
|
||||
// Make sure the header-only files compile :)
|
||||
|
||||
#if 0
|
||||
|
||||
#include "sharedSynchronization/CountingSemaphore.h"
|
||||
#include "sharedSynchronization/BlockingPointer.h"
|
||||
#include "sharedSynchronization/BlockingQueue.h"
|
||||
#include "sharedSynchronization/WriteOnce.h"
|
||||
|
||||
Mutex t;
|
||||
BlockingQueue<int> bqint(t, 0, 0);
|
||||
BlockingPointer<int> bpint(t, 0, 0);
|
||||
WriteOnce<int> woint;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Thread.h
|
||||
// Acy Stapp
|
||||
//
|
||||
// Copyright 6/19/2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_Thread_h
|
||||
#define INCLUDED_Thread_h
|
||||
|
||||
#include "sharedSynchronization/InterlockedInteger.h"
|
||||
|
||||
template <class T> class TypedThreadHandle;
|
||||
|
||||
class Thread
|
||||
{
|
||||
// Visual studio fails to compile this valid code
|
||||
// template <class T> friend TypedThreadHandle;
|
||||
public:
|
||||
static void install();
|
||||
static void remove();
|
||||
|
||||
Thread();
|
||||
Thread(const std::string &i_name);
|
||||
|
||||
void kill();
|
||||
bool done();
|
||||
void wait();
|
||||
|
||||
enum ePriority
|
||||
{
|
||||
kIdle = 0,
|
||||
kLow = 1,
|
||||
kNormal = 2,
|
||||
kHigh = 3,
|
||||
kCritical = 4
|
||||
};
|
||||
void setPriority(ePriority priority);
|
||||
void suspend();
|
||||
void resume();
|
||||
|
||||
const std::string &getName() const;
|
||||
void setName(const std::string &i_name);
|
||||
|
||||
static Thread * getCurrentThread();
|
||||
static Thread * getMainThread();
|
||||
protected:
|
||||
virtual ~Thread();
|
||||
virtual void run()=0;
|
||||
|
||||
HANDLE handle;
|
||||
unsigned int id;
|
||||
InterlockedInteger refcount;
|
||||
public: // should be private:, see above
|
||||
Thread(const Thread &o);
|
||||
Thread &operator =(const Thread &o);
|
||||
|
||||
void start();
|
||||
void attach(); // pick up the currently running thread
|
||||
|
||||
void ref();
|
||||
void deref();
|
||||
|
||||
std::string *name;
|
||||
|
||||
static int implindex;
|
||||
static Thread * mainThread;
|
||||
static unsigned int __stdcall threadFunc(void * data);
|
||||
};
|
||||
|
||||
inline void Thread::ref()
|
||||
{
|
||||
++refcount;
|
||||
}
|
||||
|
||||
inline void Thread::deref()
|
||||
{
|
||||
if (--refcount == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
inline Thread * Thread::getCurrentThread()
|
||||
{
|
||||
return static_cast<Thread *>(TlsGetValue(implindex));
|
||||
}
|
||||
|
||||
inline Thread * Thread::getMainThread()
|
||||
{
|
||||
return mainThread;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user