00001 #include "lugre_prefix.h"
00002 #include "lugre_thread.h"
00003 #include "lugre_fifo.h"
00004 #include "lugre_luabind.h"
00005 #include "lugre_luabind_direct.h"
00006 #include "lugre_scripting.h"
00007
00008 #ifdef ENABLE_THREADS
00009 #include <boost/thread/xtime.hpp>
00010 #include <boost/thread/thread.hpp>
00011 #include <boost/thread/mutex.hpp>
00012 #endif
00013
00014 namespace Lugre {
00015
00016 class cThread_NetRequest_L : public cLuaBind<cThread_NetRequest> { public:
00017
00018
00020 virtual void RegisterMethods (lua_State *L) { PROFILE
00021 #define REGISTER_METHOD(methodname) mlMethod.push_back(make_luaL_reg(#methodname,&cThread_NetRequest_L::methodname));
00022
00023 REGISTER_METHOD(Destroy);
00024 REGISTER_METHOD(IsFinished);
00025 REGISTER_METHOD(HasError);
00026
00027 #undef REGISTER_METHOD
00028
00029 lua_register(L,"CreateThread_NetRequest", &cThread_NetRequest_L::CreateThread_NetRequest);
00030 }
00031
00032
00033
00037 static int CreateThread_NetRequest (lua_State *L) { PROFILE
00038 std::string sHost = luaL_checkstring(L,1);
00039 int iPort = luaL_checkint(L,2);
00040 cFIFO* pSendData = (lua_gettop(L) >= 3 && !lua_isnil(L,3)) ? cLuaBind<cFIFO>::checkudata(L,3) : 0;
00041 cFIFO* pAnswerBuffer = (lua_gettop(L) >= 4 && !lua_isnil(L,4)) ? cLuaBind<cFIFO>::checkudata(L,4) : 0;
00042 return CreateUData(L,new cThread_NetRequest(sHost,iPort,pSendData,pAnswerBuffer));
00043 }
00044
00045
00046
00048 static int Destroy (lua_State *L) { PROFILE
00049 delete checkudata_alive(L);
00050 return 0;
00051 }
00052
00054 static int IsFinished (lua_State *L) { PROFILE
00055 lua_pushboolean(L,checkudata_alive(L)->IsFinished());
00056 return 1;
00057 }
00058
00060 static int HasError (lua_State *L) { PROFILE
00061 lua_pushboolean(L,checkudata_alive(L)->HasError());
00062 return 1;
00063 }
00064
00065 virtual const char* GetLuaTypeName () { return "lugre.thread_netrequest"; }
00066 };
00067
00068
00069
00070 class cThread_LoadFile_L : public cLuaBind<cThread_LoadFile> { public:
00071
00072
00074 virtual void RegisterMethods (lua_State *L) { PROFILE
00075 #define REGISTER_METHOD(methodname) mlMethod.push_back(make_luaL_reg(#methodname,&cThread_LoadFile_L::methodname));
00076
00077 REGISTER_METHOD(Destroy);
00078 REGISTER_METHOD(IsFinished);
00079 REGISTER_METHOD(HasError);
00080
00081 #undef REGISTER_METHOD
00082
00083 lua_register(L,"CreateThread_LoadFile", &cThread_LoadFile_L::CreateThread_LoadFile);
00084 }
00085
00086
00087
00090 static int CreateThread_LoadFile (lua_State *L) { PROFILE
00091 std::string sFilePath = luaL_checkstring(L,1);
00092 cFIFO* pAnswerBuffer = cLuaBind<cFIFO>::checkudata_alive(L,2);
00093 int iStart = (lua_gettop(L) >= 3 && !lua_isnil(L,3)) ? luaL_checkint(L,3) : 0;
00094 int iLength = (lua_gettop(L) >= 4 && !lua_isnil(L,4)) ? luaL_checkint(L,4) : -1;
00095 return CreateUData(L,new cThread_LoadFile(sFilePath,pAnswerBuffer,iStart,iLength));
00096 }
00097
00098
00099
00101 static int Destroy (lua_State *L) { PROFILE
00102 delete checkudata_alive(L);
00103 return 0;
00104 }
00105
00107 static int IsFinished (lua_State *L) { PROFILE
00108 lua_pushboolean(L,checkudata_alive(L)->IsFinished());
00109 return 1;
00110 }
00111
00113 static int HasError (lua_State *L) { PROFILE
00114 lua_pushboolean(L,checkudata_alive(L)->HasError());
00115 return 1;
00116 }
00117
00118 virtual const char* GetLuaTypeName () { return "lugre.thread_loadfile"; }
00119 };
00120
00121
00122
00123 int MyThreadSleepMilliSeconds (int iSleepTimeMilliSeconds) {
00124 #ifdef ENABLE_THREADS
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 try {
00147
00148
00149 boost::this_thread::sleep(boost::posix_time::milliseconds(iSleepTimeMilliSeconds));
00150 } catch (...) {
00151 return 2;
00152 }
00153 return 1;
00154 #else
00155 return 0;
00156 #endif
00157 }
00158
00159 #ifdef ENABLE_THREADS
00160
00161
00162 class cLugreLuaBind_Mutex : public cLuaBindDirect<boost::mutex> { public:
00163 virtual void RegisterMethods (lua_State *L) { PROFILE
00164 LUABIND_QUICKWRAP_STATIC(CreateMutex, { return CreateUData(L,new boost::mutex()); });
00165
00166 LUABIND_QUICKWRAP(GetCrossThreadHandle, { return PushPointer(L,checkudata_alive(L)); });
00167 LUABIND_QUICKWRAP_STATIC(CreateMutexFromCrossThreadHandle, { return CreateUData(L,(boost::mutex*)lua_touserdata(L,1)); });
00168
00169 LUABIND_QUICKWRAP(Destroy, { delete &GetSelf(L); });
00170 LUABIND_QUICKWRAP(LockMutex, { GetSelf(L).lock(); });
00171 LUABIND_QUICKWRAP(UnLockMutex, { GetSelf(L).unlock(); });
00172 }
00173 virtual const char* GetLuaTypeName () { return "lugre.mutex"; }
00174 };
00175
00176 class cLuaThread : public cSmartPointable { public:
00177 cFIFO mFIFOParent2Child;
00178 cFIFO mFIFOChild2Parent;
00179 boost::mutex mMutex;
00180 boost::thread* mThread;
00181 std::string msFilePath;
00182
00183 cLuaThread (std::string sFilePath);
00184 virtual ~cLuaThread () { if (mThread) { delete mThread; mThread = 0; } }
00185
00186 cFIFO& GetParent2ChildFIFO () { return mFIFOParent2Child; }
00187 cFIFO& GetChild2ParentFIFO () { return mFIFOChild2Parent; }
00188 void LockMutex () { mMutex.lock(); }
00189 void UnLockMutex () { mMutex.unlock(); }
00190 void Interrupt () { if (mThread) mThread->interrupt(); }
00191
00192 void WaitForDataFromParent () {
00193 uint32 len = 0;
00194
00195 while(true){
00196 mMutex.lock();
00197 len = mFIFOParent2Child.GetLength();
00198 mMutex.unlock();
00199
00200 if(len > 0){
00201 break;
00202 } else {
00203 MyThreadSleepMilliSeconds(1000 / 50);
00204 }
00205 }
00206 }
00207 };
00208
00209 class cLuaThread_Callable { public:
00210 cLuaThread* mSelfThreadHandle;
00211 std::string msFilePath;
00212 cLuaThread_Callable (cLuaThread* mSelfThreadHandle,std::string msFilePath) : mSelfThreadHandle(mSelfThreadHandle),msFilePath(msFilePath) {}
00213
00214 static int DontUseWarning_Client_Sleep (lua_State *L) { printf("DontUseWarning_Client_Sleep\n"); return 0; }
00215
00216
00217 static int Thread_Sleep (lua_State *L) {
00218 int iSleepTimeMilliSeconds = luaL_checkint(L,1);
00219 if (MyThreadSleepMilliSeconds(iSleepTimeMilliSeconds) == 2) { lua_pushboolean(L,true); return 1; }
00220 return 0;
00221 }
00222
00223 void operator()() { PROFILE
00224
00225
00226
00227
00228 lua_State* L = lua_open();
00229 if (!L) { printf("cLuaThread_Callable: failed to init lua state\n"); return; }
00230 cScripting::GetSingletonPtr()->InitLugreLuaEnvironment(L);
00231
00232
00233 lua_register(L,"Client_Sleep", &cLuaThread_Callable::DontUseWarning_Client_Sleep);
00234 lua_register(L,"Thread_Sleep", &cLuaThread_Callable::Thread_Sleep);
00235
00236
00237 cLuaBind<cLuaThread>::CreateUData(L, mSelfThreadHandle);
00238 lua_setglobal(L,"this_thread");
00239
00240 cLuaBind<cFIFO>::CreateUData(L, &(mSelfThreadHandle->mFIFOChild2Parent));
00241 lua_setglobal(L,"this_fifo_send");
00242
00243 cLuaBind<cFIFO>::CreateUData(L, &(mSelfThreadHandle->mFIFOParent2Child));
00244 lua_setglobal(L,"this_fifo_recv");
00245
00246 int res = luaL_dofile(L,msFilePath.c_str());
00247 if (res) {
00248 fprintf(stderr,"%s\n",lua_tostring(L,-1));
00249 MyCrash("error during cLuaThread_Callable run\n");
00250 exit(-1);
00251 }
00252 }
00253 };
00254
00255
00256
00257 cLuaThread::cLuaThread (std::string sFilePath) : mThread(0),msFilePath(sFilePath) {
00258 cLuaThread_Callable myImpl(this,sFilePath);
00259 mThread = new boost::thread(myImpl);
00260 }
00261
00262
00263 class cLuaThread_L : public cLuaBind<cLuaThread> { public:
00264
00265
00267 virtual void RegisterMethods (lua_State *L) { PROFILE
00268 #define REGISTER_METHOD(methodname) mlMethod.push_back(make_luaL_reg(#methodname,&cLuaThread_L::methodname));
00269
00270 REGISTER_METHOD(Destroy);
00271 REGISTER_METHOD(CreateFifoParent2ChildHandle);
00272 REGISTER_METHOD(CreateFifoChild2ParentHandle);
00273 REGISTER_METHOD(LockMutex);
00274 REGISTER_METHOD(UnLockMutex);
00275 REGISTER_METHOD(Interrupt);
00276 REGISTER_METHOD(WaitForDataFromParent);
00277
00278 #undef REGISTER_METHOD
00279
00280 lua_register(L,"CreateLuaThread", &cLuaThread_L::CreateLuaThread);
00281 lua_register(L,"Threads_GetHardwareConcurrency", &cLuaThread_L::Threads_GetHardwareConcurrency);
00282 }
00283
00284
00285
00287 static int CreateLuaThread (lua_State *L) { PROFILE
00288 std::string sFilePath = luaL_checkstring(L,1);
00289 return CreateUData(L,new cLuaThread(sFilePath));
00290 }
00291
00293
00294 static int Threads_GetHardwareConcurrency (lua_State *L) { PROFILE
00295 lua_pushnumber(L,boost::thread::hardware_concurrency());
00296 return 1;
00297 }
00298
00299
00300
00301
00302
00303
00305 static int CreateFifoParent2ChildHandle (lua_State *L) { PROFILE
00306 cFIFO& pFIFO = checkudata_alive(L)->GetParent2ChildFIFO();
00307 return cLuaBind<cFIFO>::CreateUData(L,&pFIFO);
00308 }
00309
00310
00312 static int CreateFifoChild2ParentHandle (lua_State *L) { PROFILE
00313 cFIFO& pFIFO = checkudata_alive(L)->GetChild2ParentFIFO();
00314 return cLuaBind<cFIFO>::CreateUData(L,&pFIFO);
00315 }
00316
00318 static int LockMutex (lua_State *L) { PROFILE checkudata_alive(L)->LockMutex(); return 0; }
00320 static int UnLockMutex (lua_State *L) { PROFILE checkudata_alive(L)->UnLockMutex(); return 0; }
00322 static int Interrupt (lua_State *L) { PROFILE checkudata_alive(L)->Interrupt(); return 0; }
00323
00325 static int WaitForDataFromParent (lua_State *L) { PROFILE checkudata_alive(L)->WaitForDataFromParent(); return 0; }
00326
00328 static int Destroy (lua_State *L) { PROFILE
00329 delete checkudata_alive(L);
00330 return 0;
00331 }
00332
00333 virtual const char* GetLuaTypeName () { return "lugre.luathread"; }
00334 };
00335
00336
00337
00338
00339
00340 #endif
00341
00343 void cThread_NetRequest::LuaRegister (lua_State *L) { PROFILE
00344 cLuaBind<cThread_NetRequest>::GetSingletonPtr(new cThread_NetRequest_L())->LuaRegister(L);
00345 }
00346 void cThread_LoadFile::LuaRegister (lua_State *L) { PROFILE
00347 cLuaBind<cThread_LoadFile>::GetSingletonPtr(new cThread_LoadFile_L())->LuaRegister(L);
00348 }
00349
00350 void LuaRegisterThreading (lua_State* L) {
00351 cThread_NetRequest::LuaRegister(L);
00352 cThread_LoadFile::LuaRegister(L);
00353 #ifdef ENABLE_THREADS
00354 cLuaBindDirect<boost::mutex >::GetSingletonPtr(new cLugreLuaBind_Mutex( ))->LuaRegister(L);
00355 cLuaBind<cLuaThread>::GetSingletonPtr(new cLuaThread_L())->LuaRegister(L);
00356 #endif
00357 }
00358
00359
00360 };