wrap_Thread.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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 "wrap_Thread.h"
  21. namespace love
  22. {
  23. namespace thread
  24. {
  25. Thread *luax_checkthread(lua_State *L, int idx)
  26. {
  27. return luax_checktype<Thread>(L, idx, "Thread", THREAD_THREAD_T);
  28. }
  29. int w_Thread_start(lua_State *L)
  30. {
  31. Thread *t = luax_checkthread(L, 1);
  32. t->start();
  33. return 0;
  34. }
  35. int w_Thread_wait(lua_State *L)
  36. {
  37. Thread *t = luax_checkthread(L, 1);
  38. t->wait();
  39. return 0;
  40. }
  41. int w_Thread_getName(lua_State *L)
  42. {
  43. Thread *t = luax_checkthread(L, 1);
  44. // allow names containing \0
  45. luax_pushstring(L, t->getName());
  46. return 1;
  47. }
  48. int w_Thread_get(lua_State *L)
  49. {
  50. Thread *t = luax_checkthread(L, 1);
  51. std::string name = luax_checkstring(L, 2);
  52. t->lock();
  53. Variant *v = t->get(name);
  54. t->clear(name);
  55. t->unlock();
  56. if (!v)
  57. {
  58. lua_pushnil(L);
  59. return 1;
  60. }
  61. v->toLua(L);
  62. t->lock();
  63. v->release();
  64. t->unlock();
  65. return 1;
  66. }
  67. int w_Thread_getKeys(lua_State *L)
  68. {
  69. Thread *t = luax_checkthread(L, 1);
  70. t->lock();
  71. std::vector<std::string> keys = t->getKeys();
  72. t->unlock();
  73. lua_createtable(L, keys.size(), 0);
  74. int i = 1;
  75. for (std::vector<std::string>::iterator it = keys.begin(); it != keys.end(); it++)
  76. {
  77. lua_pushnumber(L, i++);
  78. luax_pushstring(L, *it);
  79. lua_settable(L, -3);
  80. }
  81. return 1;
  82. }
  83. int w_Thread_demand(lua_State *L)
  84. {
  85. Thread *t = luax_checkthread(L, 1);
  86. std::string name = luax_checkstring(L, 2);
  87. t->lock();
  88. Variant *v = t->demand(name);
  89. t->clear(name);
  90. t->unlock();
  91. if (!v)
  92. {
  93. lua_pushnil(L);
  94. return 1;
  95. }
  96. v->toLua(L);
  97. t->lock();
  98. v->release();
  99. t->unlock();
  100. return 1;
  101. }
  102. int w_Thread_peek(lua_State *L)
  103. {
  104. Thread *t = luax_checkthread(L, 1);
  105. std::string name = luax_checkstring(L, 2);
  106. t->lock();
  107. Variant *v = t->get(name);
  108. t->unlock();
  109. if (!v)
  110. {
  111. lua_pushnil(L);
  112. return 1;
  113. }
  114. v->toLua(L);
  115. t->lock();
  116. v->release();
  117. t->unlock();
  118. return 1;
  119. }
  120. int w_Thread_set(lua_State *L)
  121. {
  122. Thread *t = luax_checkthread(L, 1);
  123. std::string name = luax_checkstring(L, 2);
  124. Variant *v = Variant::fromLua(L, 3);
  125. if (!v)
  126. return luaL_error(L, "Expected boolean, number, string or userdata");
  127. t->set(name, v);
  128. t->lock();
  129. v->release();
  130. t->unlock();
  131. return 0;
  132. }
  133. static const luaL_Reg type_functions[] = {
  134. { "start", w_Thread_start },
  135. { "wait", w_Thread_wait },
  136. { "getName", w_Thread_getName },
  137. { "get", w_Thread_get },
  138. { "getKeys", w_Thread_getKeys },
  139. { "demand", w_Thread_demand },
  140. { "peek", w_Thread_peek },
  141. { "set", w_Thread_set },
  142. { 0, 0 }
  143. };
  144. int luaopen_thread(lua_State *L)
  145. {
  146. return luax_register_type(L, "Thread", type_functions);
  147. }
  148. static ThreadModule *instance;
  149. int w_newThread(lua_State *L)
  150. {
  151. std::string name = luax_checkstring(L, 1);
  152. love::Data *data;
  153. if (lua_isstring(L, 2))
  154. luax_convobj(L, 2, "filesystem", "newFile");
  155. if (luax_istype(L, 2, FILESYSTEM_FILE_T))
  156. {
  157. try
  158. {
  159. data = luax_checktype<love::filesystem::File>(L, 2, "File", FILESYSTEM_FILE_T)->read();
  160. }
  161. catch (love::Exception & e)
  162. {
  163. return luaL_error(L, e.what());
  164. }
  165. }
  166. else
  167. {
  168. data = luax_checktype<love::Data>(L, 2, "Data", DATA_T);
  169. data->retain();
  170. }
  171. Thread *t = instance->newThread(name, data);
  172. // do not worry, file->read() returns retained data
  173. data->release();
  174. if (!t)
  175. return luaL_error(L, "A thread with that name already exists.");
  176. luax_newtype(L, "Thread", THREAD_THREAD_T, (void*)t);
  177. return 1;
  178. }
  179. int w_getThreads(lua_State *L)
  180. {
  181. unsigned count = instance->getThreadCount();
  182. Thread **list = new Thread*[count];
  183. instance->getThreads(list);
  184. lua_newtable(L);
  185. for (unsigned int i = 0; i<count; i++)
  186. {
  187. // allow names containing \0
  188. luax_pushstring(L, list[i]->getName());
  189. luax_newtype(L, "Thread", THREAD_THREAD_T, (void*) list[i]);
  190. list[i]->lock();
  191. list[i]->retain();
  192. list[i]->unlock();
  193. lua_settable(L, -3);
  194. }
  195. delete[] list;
  196. return 1;
  197. }
  198. int w_getThread(lua_State *L)
  199. {
  200. if (lua_isnoneornil(L, 1))
  201. {
  202. lua_getglobal(L, "love");
  203. lua_getfield(L, -1, "_curthread");
  204. return 1;
  205. }
  206. std::string name = luax_checkstring(L, 1);
  207. Thread *t = instance->getThread(name);
  208. if (t)
  209. {
  210. luax_newtype(L, "Thread", THREAD_THREAD_T, (void*)t);
  211. t->lock();
  212. t->retain();
  213. t->unlock();
  214. }
  215. else
  216. lua_pushnil(L);
  217. return 1;
  218. }
  219. // List of functions to wrap.
  220. static const luaL_Reg module_functions[] = {
  221. { "newThread", w_newThread },
  222. { "getThread", w_getThread },
  223. { "getThreads", w_getThreads },
  224. { 0, 0 }
  225. };
  226. static const lua_CFunction types[] = {
  227. luaopen_thread,
  228. 0
  229. };
  230. int luaopen_love_thread(lua_State *L)
  231. {
  232. if (instance == 0)
  233. {
  234. try
  235. {
  236. instance = new ThreadModule();
  237. lua_getglobal(L, "love");
  238. Thread *curthread = instance->getThread("main");
  239. curthread->lock();
  240. curthread->retain();
  241. curthread->unlock();
  242. luax_newtype(L, "Thread", THREAD_THREAD_T, (void*)curthread);
  243. lua_setfield(L, -2, "_curthread");
  244. }
  245. catch (Exception & e)
  246. {
  247. return luaL_error(L, e.what());
  248. }
  249. }
  250. else
  251. instance->retain();
  252. WrappedModule w;
  253. w.module = instance;
  254. w.name = "thread";
  255. w.flags = MODULE_T;
  256. w.functions = module_functions;
  257. w.types = types;
  258. return luax_register_module(L, w);
  259. }
  260. }
  261. }