From f521bff27c2cbfda0662500c13454b7d9b0bcca8 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 14 Jan 2014 01:29:38 -0700 Subject: [PATCH] Added sharedThread library --- engine/shared/library/CMakeLists.txt | 1 + .../library/sharedThread/CMakeLists.txt | 11 + .../public/sharedThread/FirstSharedThread.h | 1 + .../include/public/sharedThread/RunThread.h | 1 + .../public/sharedThread/SetupSharedThread.h | 1 + .../include/public/sharedThread/Thread.h | 7 + .../public/sharedThread/ThreadHandle.h | 1 + .../library/sharedThread/src/CMakeLists.txt | 40 ++++ .../library/sharedThread/src/linux/Thread.cpp | 159 ++++++++++++++ .../library/sharedThread/src/linux/Thread.h | 100 +++++++++ .../src/shared/FirstSharedThread.h | 17 ++ .../sharedThread/src/shared/RunThread.cpp | 44 ++++ .../sharedThread/src/shared/RunThread.h | 201 ++++++++++++++++++ .../src/shared/SetupSharedThread.cpp | 33 +++ .../src/shared/SetupSharedThread.h | 28 +++ .../sharedThread/src/shared/ThreadHandle.h | 127 +++++++++++ .../src/win32/FirstSharedThread.cpp | 8 + .../library/sharedThread/src/win32/Thread.cpp | 179 ++++++++++++++++ .../library/sharedThread/src/win32/Thread.h | 94 ++++++++ 19 files changed, 1053 insertions(+) create mode 100644 engine/shared/library/sharedThread/CMakeLists.txt create mode 100644 engine/shared/library/sharedThread/include/public/sharedThread/FirstSharedThread.h create mode 100644 engine/shared/library/sharedThread/include/public/sharedThread/RunThread.h create mode 100644 engine/shared/library/sharedThread/include/public/sharedThread/SetupSharedThread.h create mode 100644 engine/shared/library/sharedThread/include/public/sharedThread/Thread.h create mode 100644 engine/shared/library/sharedThread/include/public/sharedThread/ThreadHandle.h create mode 100644 engine/shared/library/sharedThread/src/CMakeLists.txt create mode 100644 engine/shared/library/sharedThread/src/linux/Thread.cpp create mode 100644 engine/shared/library/sharedThread/src/linux/Thread.h create mode 100644 engine/shared/library/sharedThread/src/shared/FirstSharedThread.h create mode 100644 engine/shared/library/sharedThread/src/shared/RunThread.cpp create mode 100644 engine/shared/library/sharedThread/src/shared/RunThread.h create mode 100644 engine/shared/library/sharedThread/src/shared/SetupSharedThread.cpp create mode 100644 engine/shared/library/sharedThread/src/shared/SetupSharedThread.h create mode 100644 engine/shared/library/sharedThread/src/shared/ThreadHandle.h create mode 100644 engine/shared/library/sharedThread/src/win32/FirstSharedThread.cpp create mode 100644 engine/shared/library/sharedThread/src/win32/Thread.cpp create mode 100644 engine/shared/library/sharedThread/src/win32/Thread.h diff --git a/engine/shared/library/CMakeLists.txt b/engine/shared/library/CMakeLists.txt index 01f77532..2d6a7ff2 100644 --- a/engine/shared/library/CMakeLists.txt +++ b/engine/shared/library/CMakeLists.txt @@ -6,3 +6,4 @@ add_subdirectory(sharedFoundationTypes) add_subdirectory(sharedMemoryManager) add_subdirectory(sharedNetworkMessages) add_subdirectory(sharedSynchronization) +add_subdirectory(sharedThread) diff --git a/engine/shared/library/sharedThread/CMakeLists.txt b/engine/shared/library/sharedThread/CMakeLists.txt new file mode 100644 index 00000000..44b5ae5a --- /dev/null +++ b/engine/shared/library/sharedThread/CMakeLists.txt @@ -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) diff --git a/engine/shared/library/sharedThread/include/public/sharedThread/FirstSharedThread.h b/engine/shared/library/sharedThread/include/public/sharedThread/FirstSharedThread.h new file mode 100644 index 00000000..cc217b5e --- /dev/null +++ b/engine/shared/library/sharedThread/include/public/sharedThread/FirstSharedThread.h @@ -0,0 +1 @@ +#include "../../src/shared/FirstSharedThread.h" diff --git a/engine/shared/library/sharedThread/include/public/sharedThread/RunThread.h b/engine/shared/library/sharedThread/include/public/sharedThread/RunThread.h new file mode 100644 index 00000000..e0535be3 --- /dev/null +++ b/engine/shared/library/sharedThread/include/public/sharedThread/RunThread.h @@ -0,0 +1 @@ +#include "../../src/shared/RunThread.h" diff --git a/engine/shared/library/sharedThread/include/public/sharedThread/SetupSharedThread.h b/engine/shared/library/sharedThread/include/public/sharedThread/SetupSharedThread.h new file mode 100644 index 00000000..2b83fce2 --- /dev/null +++ b/engine/shared/library/sharedThread/include/public/sharedThread/SetupSharedThread.h @@ -0,0 +1 @@ +#include "../../src/shared/SetupSharedThread.h" diff --git a/engine/shared/library/sharedThread/include/public/sharedThread/Thread.h b/engine/shared/library/sharedThread/include/public/sharedThread/Thread.h new file mode 100644 index 00000000..828c1444 --- /dev/null +++ b/engine/shared/library/sharedThread/include/public/sharedThread/Thread.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 diff --git a/engine/shared/library/sharedThread/include/public/sharedThread/ThreadHandle.h b/engine/shared/library/sharedThread/include/public/sharedThread/ThreadHandle.h new file mode 100644 index 00000000..7f9c7cdd --- /dev/null +++ b/engine/shared/library/sharedThread/include/public/sharedThread/ThreadHandle.h @@ -0,0 +1 @@ +#include "../../src/shared/ThreadHandle.h" diff --git a/engine/shared/library/sharedThread/src/CMakeLists.txt b/engine/shared/library/sharedThread/src/CMakeLists.txt new file mode 100644 index 00000000..3d4ed191 --- /dev/null +++ b/engine/shared/library/sharedThread/src/CMakeLists.txt @@ -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} +) diff --git a/engine/shared/library/sharedThread/src/linux/Thread.cpp b/engine/shared/library/sharedThread/src/linux/Thread.cpp new file mode 100644 index 00000000..90de4e55 --- /dev/null +++ b/engine/shared/library/sharedThread/src/linux/Thread.cpp @@ -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 + +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(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 bqint(t, 0, 0); +BlockingPointer bpint(t, 0, 0); +WriteOnce woint; + +#endif diff --git a/engine/shared/library/sharedThread/src/linux/Thread.h b/engine/shared/library/sharedThread/src/linux/Thread.h new file mode 100644 index 00000000..0c2faf80 --- /dev/null +++ b/engine/shared/library/sharedThread/src/linux/Thread.h @@ -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 + +class Thread +{ + template 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(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 diff --git a/engine/shared/library/sharedThread/src/shared/FirstSharedThread.h b/engine/shared/library/sharedThread/src/shared/FirstSharedThread.h new file mode 100644 index 00000000..21612208 --- /dev/null +++ b/engine/shared/library/sharedThread/src/shared/FirstSharedThread.h @@ -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 diff --git a/engine/shared/library/sharedThread/src/shared/RunThread.cpp b/engine/shared/library/sharedThread/src/shared/RunThread.cpp new file mode 100644 index 00000000..3f5e0962 --- /dev/null +++ b/engine/shared/library/sharedThread/src/shared/RunThread.cpp @@ -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 (new FuncPtrThreadZero(func)); +} + +FuncPtrThreadZero::Handle runNamedThread(const std::string &name, void (* func)()) +{ + return TypedThreadHandle (new FuncPtrThreadZero(name, func)); +} + +#if 0 +// Testing stuff + +class testclass +{ +public: + void zeroArg() {} + void oneArg(testclass *) {} + void twoArg(testclass *, int) {} +}; + +testclass m; + +typedef MemberFunctionThreadZero::Handle AsyncTestMemberFunctionZero; +AsyncTestMemberFunctionZero temp = runThread(m, testclass::zeroArg); + +typedef MemberFunctionThreadOne::Handle AsyncTestMemberFunctionOne; +AsyncTestMemberFunctionOne temp2 = runThread(m, testclass::oneArg, &m); + +typedef MemberFunctionThreadTwo::Handle AsyncTestMemberFunctionTwo; +AsyncTestMemberFunctionTwo temp3 = runThread(m, testclass::twoArg, &m, 4); +#endif diff --git a/engine/shared/library/sharedThread/src/shared/RunThread.h b/engine/shared/library/sharedThread/src/shared/RunThread.h new file mode 100644 index 00000000..ebc4de6f --- /dev/null +++ b/engine/shared/library/sharedThread/src/shared/RunThread.h @@ -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 MemberFunctionThreadZero: public Thread +{ +public: + typedef void (CLASS::* FUNCTION)(void); + typedef TypedThreadHandle > 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 +typename MemberFunctionThreadZero::Handle runThread(CLASS &o, typename MemberFunctionThreadZero::FUNCTION function) +{ + return TypedThreadHandle > (new MemberFunctionThreadZero(o, function)); +} + +template +TypedThreadHandle > runNamedThread(const std::string &name, CLASS &o, typename MemberFunctionThreadZero::FUNCTION function) +{ + return TypedThreadHandle > (new MemberFunctionThreadZero(name, o, function)); +} + +// ------------------------------------------------------------------------------------------ + +template +class MemberFunctionThreadOne: public Thread +{ +public: + typedef void (CLASS::* FUNCTION)(ARG1 o); + typedef TypedThreadHandle > 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 +TypedThreadHandle > runThread(CLASS &o, void (CLASS::* function)(ARG1 o), ARG1 arg1) +{ + return TypedThreadHandle > (new MemberFunctionThreadOne(o, function, arg1)); +} + +template +TypedThreadHandle > runNamedThread(const std::string &name, CLASS &o, void (CLASS::* function)(ARG1 o), ARG1 arg1) +{ + return TypedThreadHandle > (new MemberFunctionThreadOne(name, o, function, arg1)); +} + +// ------------------------------------------------------------------------------------------ + +template +class MemberFunctionThreadTwo: public Thread +{ +public: + typedef void (CLASS::* FUNCTION)(ARG1 o, ARG2 p); + typedef TypedThreadHandle > 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 +TypedThreadHandle > runThread(CLASS &o, void (CLASS::* function)(ARG1 o, ARG2 p), ARG1 arg1, ARG2 arg2) +{ + return TypedThreadHandle > (new MemberFunctionThreadTwo(o, function, arg1, arg2)); +} + +template +TypedThreadHandle > runNamedThread(const std::string &name, CLASS &o, void (CLASS::* function)(ARG1 o, ARG2 p), ARG1 arg1, ARG2 arg2) +{ + return TypedThreadHandle > (new MemberFunctionThreadTwo(name, o, function, arg1, arg2)); +} + +// ----------------------------------------------------------------------------- + +class FuncPtrThreadZero: public Thread +{ +public: + typedef void (* FUNCTION)(); + typedef TypedThreadHandle 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 runThread(FuncPtrThreadZero::FUNCTION func); +TypedThreadHandle runNamedThread(const std::string &name, FuncPtrThreadZero::FUNCTION func); + +// ----------------------------------------------------------------------------- + +template +class FuncPtrThreadOne: public Thread +{ +public: + typedef void (* FUNCTION)(ARG1 arg1); + typedef TypedThreadHandle > 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 +TypedThreadHandle > runThread(typename FuncPtrThreadOne::FUNCTION func, ARG1 arg1) +{ + return TypedThreadHandle > (new FuncPtrThreadOne(func, arg1)); +} + +template +TypedThreadHandle > runNamedThread(const std::string &name, typename FuncPtrThreadOne::FUNCTION func, ARG1 arg1) +{ + return TypedThreadHandle > (new FuncPtrThreadOne(name, func, arg1)); +} + +// ----------------------------------------------------------------------------- + +template +class FuncPtrThreadTwo: public Thread +{ +public: + typedef void (* FUNCTION)(ARG1, ARG2); + typedef TypedThreadHandle > 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 +TypedThreadHandle > runThread(typename FuncPtrThreadTwo::FUNCTION func, ARG1 arg1, ARG2 arg2) +{ + return TypedThreadHandle > (new FuncPtrThreadTwo(func, arg1, arg2)); +} + +template +TypedThreadHandle > runNamedThread(const std::string &name, typename FuncPtrThreadTwo::FUNCTION func, ARG1 arg1, ARG2 arg2) +{ + return TypedThreadHandle > (new FuncPtrThreadTwo(name, func, arg1, arg2)); +} + +#endif diff --git a/engine/shared/library/sharedThread/src/shared/SetupSharedThread.cpp b/engine/shared/library/sharedThread/src/shared/SetupSharedThread.cpp new file mode 100644 index 00000000..d3b1d15c --- /dev/null +++ b/engine/shared/library/sharedThread/src/shared/SetupSharedThread.cpp @@ -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(); +} + +// ====================================================================== diff --git a/engine/shared/library/sharedThread/src/shared/SetupSharedThread.h b/engine/shared/library/sharedThread/src/shared/SetupSharedThread.h new file mode 100644 index 00000000..5a5ce968 --- /dev/null +++ b/engine/shared/library/sharedThread/src/shared/SetupSharedThread.h @@ -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 diff --git a/engine/shared/library/sharedThread/src/shared/ThreadHandle.h b/engine/shared/library/sharedThread/src/shared/ThreadHandle.h new file mode 100644 index 00000000..5c0ada40 --- /dev/null +++ b/engine/shared/library/sharedThread/src/shared/ThreadHandle.h @@ -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 TypedThreadHandle +{ +public: + typedef TypedThreadHandle ThreadHandle; + + TypedThreadHandle(); + ~TypedThreadHandle(); + explicit TypedThreadHandle(T * i); + TypedThreadHandle(const TypedThreadHandle &o); + + template + TypedThreadHandle &operator =(const TypedThreadHandle &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 TypedThreadHandle; + T * getImpl() const { return const_cast(impl); } +protected: + T * impl; +}; + +typedef TypedThreadHandle ThreadHandle; + +template +TypedThreadHandle::TypedThreadHandle() +: impl(0) +{ +} + +template +TypedThreadHandle::TypedThreadHandle(T * i) +: impl(i) +{ + if (impl) + { + impl->ref(); + impl->start(); + } +} + +template +TypedThreadHandle::TypedThreadHandle(const TypedThreadHandle &o) +: impl(o.impl) +{ + if (impl) + impl->ref(); +} + +template +TypedThreadHandle::~TypedThreadHandle() +{ + if (impl) + impl->deref(); + impl = 0; +} + +template +TypedThreadHandle TypedThreadHandle::getCurrentThread() +{ + return TypedThreadHandle(Thread::getCurrentThread()); +} + +template +TypedThreadHandle TypedThreadHandle::getMainThread() +{ + return TypedThreadHandle(Thread::getMainThread()); +} + +template +void TypedThreadHandle::waitZero() +{ + if (impl) + { + impl->wait(); + impl->deref(); + } + impl = 0; +} + +template +void TypedThreadHandle::zero() +{ + if (impl) + impl->deref(); + impl = 0; +} + +#endif diff --git a/engine/shared/library/sharedThread/src/win32/FirstSharedThread.cpp b/engine/shared/library/sharedThread/src/win32/FirstSharedThread.cpp new file mode 100644 index 00000000..44b0e50c --- /dev/null +++ b/engine/shared/library/sharedThread/src/win32/FirstSharedThread.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstThread.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedThread/FirstSharedThread.h" diff --git a/engine/shared/library/sharedThread/src/win32/Thread.cpp b/engine/shared/library/sharedThread/src/win32/Thread.cpp new file mode 100644 index 00000000..2db63ced --- /dev/null +++ b/engine/shared/library/sharedThread/src/win32/Thread.cpp @@ -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 + +#include + +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(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 bqint(t, 0, 0); +BlockingPointer bpint(t, 0, 0); +WriteOnce woint; + +#endif \ No newline at end of file diff --git a/engine/shared/library/sharedThread/src/win32/Thread.h b/engine/shared/library/sharedThread/src/win32/Thread.h new file mode 100644 index 00000000..6d59c27d --- /dev/null +++ b/engine/shared/library/sharedThread/src/win32/Thread.h @@ -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 TypedThreadHandle; + +class Thread +{ + // Visual studio fails to compile this valid code + // template 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(TlsGetValue(implindex)); +} + +inline Thread * Thread::getMainThread() +{ + return mainThread; +} + +#endif \ No newline at end of file