Thread.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /**
  2. * Copyright (c) 2006-2010 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include <common/config.h>
  21. #include "Thread.h"
  22. #ifdef LOVE_BUILD_STANDALONE
  23. extern "C" int luaopen_love(lua_State * L);
  24. #endif // LOVE_BUILD_STANDALONE
  25. extern "C" int luaopen_love_thread(lua_State *L);
  26. namespace love
  27. {
  28. namespace thread
  29. {
  30. namespace sdl
  31. {
  32. int threadfunc(ThreadData *comm)
  33. {
  34. lua_State * L = lua_open();
  35. luaL_openlibs(L);
  36. #ifdef LOVE_BUILD_STANDALONE
  37. love::luax_preload(L, luaopen_love, "love");
  38. luaopen_love(L);
  39. #endif // LOVE_BUILD_STANDALONE
  40. luaopen_love_thread(L);
  41. lua_pushstring(L, comm->getName());
  42. luax_convobj(L, lua_gettop(L), "thread", "getThread");
  43. lua_setglobal(L, "thread");
  44. if(luaL_dostring(L, comm->getCode()) == 1)
  45. {
  46. ThreadVariant *v = new ThreadVariant(lua_tostring(L, -1));
  47. comm->setValue("error", v);
  48. v->release();
  49. }
  50. lua_close(L);
  51. return 0;
  52. }
  53. ThreadVariant::ThreadVariant(bool boolean)
  54. {
  55. type = BOOLEAN;
  56. data.boolean = boolean;
  57. }
  58. ThreadVariant::ThreadVariant(double number)
  59. {
  60. type = NUMBER;
  61. data.number = number;
  62. }
  63. ThreadVariant::ThreadVariant(const char *string)
  64. {
  65. type = STRING;
  66. size_t len = strlen(string);
  67. char *buf = new char[len+1];
  68. memset(buf, 0, len+1);
  69. memcpy(buf, string, len);
  70. data.string = buf;
  71. }
  72. ThreadVariant::ThreadVariant(void *userdata)
  73. {
  74. type = LUSERDATA;
  75. data.userdata = userdata;
  76. }
  77. ThreadVariant::ThreadVariant(Type udatatype, void *userdata)
  78. {
  79. type = FUSERDATA;
  80. this->udatatype = udatatype;
  81. Proxy *p = (Proxy *) userdata;
  82. flags = p->flags;
  83. data.userdata = p->data;
  84. ((love::Object *) data.userdata)->retain();
  85. }
  86. ThreadVariant::~ThreadVariant()
  87. {
  88. switch(type)
  89. {
  90. case STRING:
  91. delete[] data.string;
  92. break;
  93. case FUSERDATA:
  94. ((love::Object *) data.userdata)->release();
  95. break;
  96. default:
  97. break;
  98. }
  99. }
  100. ThreadData::ThreadData(const char *name, const char *code)
  101. {
  102. size_t len = strlen(name);
  103. this->name = new char[len+1];
  104. memset(this->name, 0, len+1);
  105. memcpy(this->name, name, len);
  106. if (code)
  107. {
  108. len = strlen(code);
  109. this->code = new char[len+1];
  110. memset(this->code, 0, len+1);
  111. memcpy(this->code, code, len);
  112. }
  113. else
  114. this->code = 0;
  115. }
  116. ThreadData::~ThreadData()
  117. {
  118. delete[] name;
  119. delete[] code;
  120. }
  121. const char *ThreadData::getCode()
  122. {
  123. return code;
  124. }
  125. const char *ThreadData::getName()
  126. {
  127. return name;
  128. }
  129. ThreadVariant* ThreadData::getValue(std::string name)
  130. {
  131. if (shared.count(name) == 0)
  132. return 0;
  133. return shared[name];
  134. }
  135. void ThreadData::clearValue(std::string name)
  136. {
  137. if (shared.count(name) == 0)
  138. return;
  139. shared[name]->release();
  140. shared.erase(name);
  141. }
  142. void ThreadData::setValue(std::string name, ThreadVariant *v)
  143. {
  144. if (shared.count(name) != 0)
  145. shared[name]->release();
  146. v->retain();
  147. shared[name] = v;
  148. }
  149. Thread::Thread(love::thread::ThreadModule *module, std::string name, love::Data *data)
  150. : handle(0), module(module), name(name), isThread(true)
  151. {
  152. module->retain();
  153. unsigned int len = data->getSize();
  154. this->data = new char[len+1];
  155. memset(this->data, 0, len+1);
  156. memcpy(this->data, data->getData(), len);
  157. comm = new ThreadData(name.c_str(), this->data);
  158. mutex = SDL_CreateMutex();
  159. cond = SDL_CreateCond();
  160. }
  161. Thread::Thread(love::thread::ThreadModule *module, std::string name)
  162. : handle(0), module(module), name(name), data(0), isThread(false)
  163. {
  164. module->retain();
  165. comm = new ThreadData(name.c_str(), NULL);
  166. mutex = SDL_CreateMutex();
  167. cond = SDL_CreateCond();
  168. }
  169. Thread::~Thread()
  170. {
  171. if (data)
  172. delete[] data;
  173. delete comm;
  174. if (handle)
  175. SDL_KillThread(handle);
  176. module->unregister(name);
  177. SDL_DestroyMutex(mutex);
  178. SDL_DestroyCond(cond);
  179. module->release();
  180. }
  181. void Thread::start()
  182. {
  183. if (!handle && isThread)
  184. handle = SDL_CreateThread((int (*)(void*)) threadfunc, (void*) comm);
  185. }
  186. void Thread::kill()
  187. {
  188. if (handle)
  189. {
  190. SDL_KillThread(handle);
  191. handle = 0;
  192. }
  193. }
  194. void Thread::wait()
  195. {
  196. if (handle)
  197. {
  198. SDL_WaitThread(handle, NULL);
  199. handle = 0;
  200. }
  201. }
  202. void Thread::lock()
  203. {
  204. SDL_mutexP(mutex);
  205. }
  206. void Thread::unlock()
  207. {
  208. SDL_mutexV(mutex);
  209. }
  210. std::string Thread::getName()
  211. {
  212. return name;
  213. }
  214. ThreadVariant *Thread::receive(std::string name)
  215. {
  216. lock();
  217. ThreadVariant *v = comm->getValue(name);
  218. unlock();
  219. return v;
  220. }
  221. ThreadVariant *Thread::demand(std::string name)
  222. {
  223. lock();
  224. ThreadVariant *v = comm->getValue(name);
  225. while (!v)
  226. {
  227. if (comm->getValue("error"))
  228. return 0;
  229. SDL_CondWait(cond, mutex);
  230. v = comm->getValue(name);
  231. }
  232. unlock();
  233. return v;
  234. }
  235. void Thread::clear(std::string name)
  236. {
  237. lock();
  238. comm->clearValue(name);
  239. unlock();
  240. }
  241. void Thread::send(std::string name, ThreadVariant *v)
  242. {
  243. lock();
  244. comm->setValue(name, v);
  245. unlock();
  246. SDL_CondBroadcast(cond);
  247. }
  248. ThreadModule::ThreadModule()
  249. {
  250. threads["main"] = new Thread(this, "main");
  251. }
  252. ThreadModule::~ThreadModule()
  253. {
  254. for (threadlist_t::iterator i = threads.begin(); i != threads.end(); i++)
  255. {
  256. i->second->kill();
  257. }
  258. }
  259. Thread *ThreadModule::newThread(std::string name, love::Data *data)
  260. {
  261. if (threads.count(name) != 0)
  262. return 0;
  263. Thread *t = new Thread(this, name, data);
  264. threads[name] = t;
  265. return t;
  266. }
  267. Thread *ThreadModule::getThread(std::string name)
  268. {
  269. if (threads.count(name) == 0)
  270. return 0;
  271. threadlist_t::iterator i = threads.find(name);
  272. return i->second;
  273. }
  274. Thread **ThreadModule::getThreads()
  275. {
  276. Thread **list = new Thread*[threads.size()+1];
  277. int c = 0;
  278. for (threadlist_t::iterator i = threads.begin(); i != threads.end(); i++, c++)
  279. {
  280. list[c] = i->second;
  281. }
  282. list[threads.size()] = 0;
  283. return list;
  284. }
  285. void ThreadModule::unregister(std::string name)
  286. {
  287. if (threads.count(name) == 0)
  288. return;
  289. threadlist_t::iterator i = threads.find(name);
  290. threads.erase(i);
  291. }
  292. const char *ThreadModule::getName() const
  293. {
  294. return "love.thread.sdl";
  295. }
  296. } // sdl
  297. } // thread
  298. } // love