• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

FunctionThread.cpp

Go to the documentation of this file.
00001 #include "FunctionThread.h"
00002 #include "RakSleep.h"
00003 
00004 using namespace RakNet;
00005 
00006 #ifdef _MSC_VER
00007 #pragma warning( push )
00008 #endif
00009 
00010 FunctionThread::FunctorAndContext WorkerThreadFunc(FunctionThread::FunctorAndContext input, bool *returnOutput, void* perThreadData)
00011 {
00012         (void) perThreadData;
00013 
00014         FunctionThread::FunctorAndContext output;
00015         input.functor->Process(input.context);
00016         output.functor=input.functor;
00017         output.context=input.context;
00018         *returnOutput=true;
00019         return output;
00020 }
00021 FunctionThread::FunctionThread()
00022 {
00023         pr=0;
00024 }
00025 FunctionThread::~FunctionThread()
00026 {
00027         StopThreads(false);
00028 }
00029 void FunctionThread::StartThreads(int numThreads)
00030 {
00031         threadPool.StartThreads(numThreads, 0, 0, 0);
00032 }
00033 void FunctionThread::StopThreads(bool blockOnCurrentProcessing)
00034 {
00035         // This ensures all waiting data is ultimately passed to a callback, so there are no leaks
00036         CancelInput();
00037         while (blockOnCurrentProcessing && threadPool.IsWorking())
00038         {
00039                 CallResultHandlers();
00040                 RakSleep(30);
00041         }
00042         threadPool.StopThreads();
00043 }
00044 void FunctionThread::Push(Functor *functor, void *context)
00045 {
00046         FunctorAndContext input;
00047         input.functor=functor;
00048         input.context=context;
00049         threadPool.AddInput(WorkerThreadFunc, input);
00050 }
00051 void FunctionThread::CallResultHandlers(void)
00052 {
00053         FunctorAndContext functorAndResult;
00054         while (threadPool.HasOutputFast() && threadPool.HasOutput())
00055         {
00056                 functorAndResult = threadPool.GetOutput();
00057                 functorAndResult.functor->HandleResult(false, functorAndResult.context);
00058                 if (pr) pr(functorAndResult);
00059         }
00060 }
00061 void FunctionThread::CancelFunctorsWithContext(bool (*cancelThisFunctor)(FunctionThread::FunctorAndContext func, void *userData), void *userData)
00062 {
00063         FunctorAndContext functorAndResult;
00064         unsigned i;
00065         threadPool.LockInput();
00066         for (i=0; i < threadPool.InputSize(); i++)
00067         {
00068                 functorAndResult = threadPool.GetInputAtIndex(i);
00069                 if (cancelThisFunctor(functorAndResult, userData))
00070                 {
00071                         functorAndResult.functor->HandleResult(true, functorAndResult.context);
00072                         if (pr) pr(functorAndResult);
00073                 }
00074         }
00075         threadPool.ClearInput();
00076         threadPool.UnlockInput();
00077 }
00078 void FunctionThread::SetPostResultFunction(void (*postResult)(FunctionThread::FunctorAndContext func))
00079 {
00080         pr=postResult;
00081 }
00082 void FunctionThread::CancelInput(void)
00083 {
00084         // We do it this way so that the callbacks get called so user-allocated data can be freed.
00085         FunctorAndContext functorAndResult;
00086         unsigned i;
00087         threadPool.LockInput();
00088         for (i=0; i < threadPool.InputSize(); i++)
00089         {
00090                 functorAndResult = threadPool.GetInputAtIndex(i);
00091                 functorAndResult.functor->HandleResult(true, functorAndResult.context);
00092                 if (pr) pr(functorAndResult);
00093         }
00094         threadPool.ClearInput();
00095         threadPool.UnlockInput();
00096 }
00097 
00098 FunctionThreadDependentClass::FunctionThreadDependentClass()
00099 {
00100         functionThreadWasAllocated=false;
00101         functionThread=0;
00102 }
00103 FunctionThreadDependentClass::~FunctionThreadDependentClass()
00104 {
00105         if (functionThreadWasAllocated)
00106                 RakNet::OP_DELETE(functionThread, __FILE__, __LINE__);
00107 }
00108 
00109 void FunctionThreadDependentClass::AssignFunctionThread(FunctionThread *ft)
00110 {
00111         if (functionThread && functionThreadWasAllocated)
00112         {
00113                 functionThread->StopThreads(true);
00114                 RakNet::OP_DELETE(functionThread, __FILE__, __LINE__);
00115         }
00116 
00117         functionThread=ft;
00118         functionThreadWasAllocated=false;
00119 }
00120 
00121 void FunctionThreadDependentClass::StartFunctionThread(void)
00122 {
00123         if (functionThread==0)
00124         {
00125                 functionThread = RakNet::OP_NEW<FunctionThread>( __FILE__, __LINE__ );
00126                 functionThreadWasAllocated=true;
00127         }
00128 
00129         functionThread->StartThreads(1);
00130 }
00131 FunctionThread *FunctionThreadDependentClass::GetFunctionThread(void) const
00132 {
00133         return functionThread;
00134 }
00135 bool FunctionThreadDependentClass::GetFunctionThreadWasAllocated(void) const
00136 {
00137         return functionThreadWasAllocated;
00138 }
00139 void FunctionThreadDependentClass::PushFunctor(Functor *functor, void *context)
00140 {
00141         StartFunctionThread();
00142         functionThread->Push(functor, context);
00143 }
00144 
00145 #ifdef _MSC_VER
00146 #pragma warning( pop )
00147 #endif

Generated on Thu Sep 30 2010 01:27:24 for RakNet by  doxygen 1.7.1