Thread.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /**
  2. * Copyright (c) 2006-2013 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. Thread::ThreadThread::ThreadThread(ThreadData *comm)
  31. : comm(comm)
  32. {
  33. }
  34. void Thread::ThreadThread::main()
  35. {
  36. lua_State *L = lua_open();
  37. luaL_openlibs(L);
  38. #ifdef LOVE_BUILD_STANDALONE
  39. love::luax_preload(L, luaopen_love, "love");
  40. luaopen_love(L);
  41. #endif // LOVE_BUILD_STANDALONE
  42. luaopen_love_thread(L);
  43. {
  44. size_t len;
  45. const char *name = comm->getName(&len);
  46. lua_pushlstring(L, name, len);
  47. }
  48. luax_convobj(L, lua_gettop(L), "thread", "getThread");
  49. lua_getglobal(L, "love");
  50. lua_pushvalue(L, -2);
  51. lua_setfield(L, -2, "_curthread");
  52. if (luaL_dostring(L, comm->getCode()) == 1)
  53. {
  54. {
  55. Lock lock((Mutex *) comm->mutex);
  56. Variant *v = new Variant(lua_tostring(L, -1), lua_strlen(L, -1));
  57. comm->setValue("error", v);
  58. v->release();
  59. }
  60. ((Conditional *) comm->cond)->broadcast();
  61. }
  62. lua_close(L);
  63. }
  64. ThreadData::ThreadData(const char *name, size_t len, const char *code, void *mutex, void *cond)
  65. : mutex(mutex), cond(cond), len(len)
  66. {
  67. this->name = new char[len+1];
  68. memset(this->name, 0, len+1);
  69. memcpy(this->name, name, len);
  70. if (code)
  71. {
  72. len = strlen(code);
  73. this->code = new char[len+1];
  74. memset(this->code, 0, len+1);
  75. memcpy(this->code, code, len);
  76. }
  77. else
  78. this->code = 0;
  79. }
  80. ThreadData::~ThreadData()
  81. {
  82. delete[] name;
  83. delete[] code;
  84. }
  85. const char *ThreadData::getCode()
  86. {
  87. return code;
  88. }
  89. const char *ThreadData::getName(size_t *len)
  90. {
  91. if (len)
  92. *len = this->len;
  93. return name;
  94. }
  95. Variant *ThreadData::getValue(const std::string &name)
  96. {
  97. if (shared.count(name) == 0)
  98. return 0;
  99. return shared[name];
  100. }
  101. void ThreadData::clearValue(const std::string &name)
  102. {
  103. if (shared.count(name) == 0)
  104. return;
  105. shared[name]->release();
  106. shared.erase(name);
  107. }
  108. void ThreadData::setValue(const std::string &name, Variant *v)
  109. {
  110. if (shared.count(name) != 0)
  111. shared[name]->release();
  112. v->retain();
  113. shared[name] = v;
  114. }
  115. std::vector<std::string> ThreadData::getKeys()
  116. {
  117. std::vector<std::string> keys;
  118. for (std::map<std::string, Variant *>::iterator it = shared.begin(); it != shared.end(); it++)
  119. {
  120. keys.push_back(it->first);
  121. }
  122. return keys;
  123. }
  124. Thread::Thread(love::thread::ThreadModule *module, const std::string &name, love::Data *data)
  125. : handle(0), module(module), name(name), isThread(true)
  126. {
  127. module->retain();
  128. unsigned int len = data->getSize();
  129. this->data = new char[len+1];
  130. memset(this->data, 0, len+1);
  131. memcpy(this->data, data->getData(), len);
  132. mutex = new Mutex();
  133. cond = new Conditional();
  134. comm = new ThreadData(name.c_str(), name.length(), this->data, mutex, cond);
  135. }
  136. Thread::Thread(love::thread::ThreadModule *module, const std::string &name)
  137. : handle(0), module(module), name(name), data(0), isThread(false)
  138. {
  139. module->retain();
  140. mutex = new Mutex();
  141. cond = new Conditional();
  142. comm = new ThreadData(name.c_str(), name.length(), NULL, mutex, cond);
  143. }
  144. Thread::~Thread()
  145. {
  146. if (data)
  147. delete[] data;
  148. delete comm;
  149. module->unregister(name);
  150. delete mutex;
  151. delete cond;
  152. module->release();
  153. }
  154. void Thread::start()
  155. {
  156. if (!handle && isThread)
  157. {
  158. handle = new ThreadThread(comm);
  159. handle->start();
  160. }
  161. }
  162. void Thread::kill()
  163. {
  164. if (handle)
  165. {
  166. Lock lock((Mutex *) _gcmutex);
  167. handle->kill();
  168. delete handle;
  169. handle = 0;
  170. }
  171. }
  172. void Thread::wait()
  173. {
  174. if (handle)
  175. {
  176. handle->wait();
  177. delete handle;
  178. handle = 0;
  179. }
  180. }
  181. void Thread::lock()
  182. {
  183. mutex->lock();
  184. }
  185. void Thread::unlock()
  186. {
  187. mutex->unlock();
  188. }
  189. std::string Thread::getName()
  190. {
  191. return name;
  192. }
  193. Variant *Thread::get(const std::string &name)
  194. {
  195. Variant *v = comm->getValue(name);
  196. if (v)
  197. v->retain();
  198. return v;
  199. }
  200. std::vector<std::string> Thread::getKeys()
  201. {
  202. return comm->getKeys();
  203. }
  204. Variant *Thread::demand(const std::string &name)
  205. {
  206. Variant *v = comm->getValue(name);
  207. while (!v)
  208. {
  209. if (comm->getValue("error"))
  210. return 0;
  211. cond->wait(mutex);
  212. v = comm->getValue(name);
  213. }
  214. v->retain();
  215. return v;
  216. }
  217. void Thread::clear(const std::string &name)
  218. {
  219. comm->clearValue(name);
  220. }
  221. void Thread::set(const std::string &name, Variant *v)
  222. {
  223. lock(); //this function explicitly locks
  224. comm->setValue(name, v); //because we need
  225. unlock(); //it to unlock here for the cond
  226. cond->broadcast();
  227. }
  228. ThreadModule::ThreadModule()
  229. {
  230. threads["main"] = new Thread(this, "main");
  231. }
  232. ThreadModule::~ThreadModule()
  233. {
  234. for (threadlist_t::iterator i = threads.begin(); i != threads.end(); i++)
  235. {
  236. i->second->kill();
  237. delete i->second;
  238. }
  239. }
  240. Thread *ThreadModule::newThread(const std::string &name, love::Data *data)
  241. {
  242. if (threads.count(name) != 0)
  243. return 0;
  244. Thread *t = new Thread(this, name, data);
  245. threads[name] = t;
  246. return t;
  247. }
  248. Thread *ThreadModule::getThread(const std::string &name)
  249. {
  250. if (threads.count(name) == 0)
  251. return 0;
  252. threadlist_t::iterator i = threads.find(name);
  253. return i->second;
  254. }
  255. void ThreadModule::getThreads(Thread **list)
  256. {
  257. int c = 0;
  258. for (threadlist_t::iterator i = threads.begin(); i != threads.end(); i++, c++)
  259. {
  260. list[c] = i->second;
  261. }
  262. }
  263. unsigned ThreadModule::getThreadCount() const
  264. {
  265. return threads.size();
  266. }
  267. void ThreadModule::unregister(const std::string &name)
  268. {
  269. if (threads.count(name) == 0)
  270. return;
  271. threadlist_t::iterator i = threads.find(name);
  272. // FIXME: shouldn't the thread be deleted?
  273. threads.erase(i);
  274. }
  275. const char *ThreadModule::getName() const
  276. {
  277. return "love.thread.sdl";
  278. }
  279. } // thread
  280. } // love