lugre_thread_L.cpp

Go to the documentation of this file.
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     // implementation of cLuaBind
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     // static methods exported to lua
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     // object methods exported to lua
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     // implementation of cLuaBind
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     // static methods exported to lua
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     // object methods exported to lua
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 // result : 0:not supported,  1:success   2:interrupted
00123 int     MyThreadSleepMilliSeconds (int iSleepTimeMilliSeconds) {
00124     #ifdef ENABLE_THREADS
00125     
00126     
00127     /*
00128     ancient boost version : 103401
00129     boost::xtime xt;
00130     boost::xtime_get(&xt, boost::TIME_UTC);
00131     int big = 1000*1000*1000;
00132     xt.sec += (iSleepTimeMilliSeconds / 1000);
00133     while (xt.nsec > big) { xt.nsec -= big; xt.sec += 1; }
00134     xt.nsec += (iSleepTimeMilliSeconds % 1000)*1000*1000;
00135     while (xt.nsec > big) { xt.nsec -= big; xt.sec += 1; }
00136     boost::thread::sleep(xt);
00137     */
00138     
00139     
00140     //~ #else
00141     //~ #define BOOST_VERSION 103401 -- ghoul : old : linux
00142     //~ #define BOOST_VERSION 103700 -- ghoul : new
00143     //~ #define BOOST_VERSION 103800 -- hagish:win
00144     // #define BOOST_LIB_VERSION "1_34_1"
00145         
00146     try {
00147         // boost::this_thread::sleep(system_time const& abs_time);  
00148         // boost::this_thread::sleep(TimeDuration const& rel_time);
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)); });    // void* so we can pass it across threads
00167         LUABIND_QUICKWRAP_STATIC(CreateMutexFromCrossThreadHandle,      { return CreateUData(L,(boost::mutex*)lua_touserdata(L,1)); });     // rewrap/recover from void*
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: // must be copyable
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     // bool     Thread_Sleep    (iSleepTimeMilliSeconds)   // returns true if it was interrupted
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 // TODO : PROFILE shouldnt be used in threads!!! racecondition (needs to be fixed by threadid compare in profile implementation)
00224         //~ msFilePath
00225         //  boost::thread::sleep()
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); // warning ! this COPIES the impl object
00260 }
00261 
00262 
00263 class cLuaThread_L : public cLuaBind<cLuaThread> { public:
00264     // implementation of cLuaBind
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     // static methods exported to lua
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         // The number of hardware threads available on the current system (e.g. number of CPUs or cores or hyperthreading units), or 0 if this information is not available. 
00294         static int          Threads_GetHardwareConcurrency  (lua_State *L) { PROFILE
00295             lua_pushnumber(L,boost::thread::hardware_concurrency()); //~ unsigned boost::thread::hardware_concurrency();
00296             return 1;
00297         }
00298         
00299         
00300             
00301     // object methods exported to lua
00302 
00303         // use LockMutex -- UnLockMutex  around access to this fifo !
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         // use LockMutex -- UnLockMutex  around access to this fifo !
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 };

Generated on Wed May 23 06:00:15 2012 for cpp by  doxygen 1.5.6