-
Notifications
You must be signed in to change notification settings - Fork 0
/
thread.cpp
102 lines (90 loc) · 2.93 KB
/
thread.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright (C) 2019 Tomoyuki Fujimori <moyu@dromozoa.com>
//
// This file is part of dromozoa-multi.
//
// dromozoa-multi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// dromozoa-multi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with dromozoa-multi. If not, see <http://www.gnu.org/licenses/>.
#include "common.hpp"
#include <sstream>
#include <dromozoa/bind/thread.hpp>
namespace dromozoa {
namespace {
thread* check_thread(lua_State* L, int arg) {
return luaX_check_udata<thread>(L, arg, "dromozoa.multi.thread");
}
void* start_routine(void* arg) {
state_handle that(static_cast<lua_State*>(arg));
int nargs = lua_tonumber(that.get(), -1);
lua_pop(that.get(), 1);
if (lua_pcall(that.get(), nargs, 0, 0) != 0) {
DROMOZOA_UNEXPECTED(lua_tostring(that.get(), -1));
}
return 0;
}
void impl_gc(lua_State* L) {
check_thread(L, 1)->~thread();
}
void impl_call(lua_State* L) {
state_handle* that = check_state_handle(L, 2);
if (!that->get()) {
luaX_throw_failure("invalid state");
}
int nargs = that->xcopy(L, 3);
luaX_push(that->get(), nargs);
try {
luaX_new<thread>(L, start_routine, that->get());
that->release();
luaX_set_metatable(L, "dromozoa.multi.thread");
} catch (const system_error& e) {
luaX_throw_failure(e.what(), e.code());
}
}
void impl_detach(lua_State* L) {
try {
check_thread(L, 1)->detach();
luaX_push_success(L);
} catch (const system_error& e) {
luaX_throw_failure(e.what(), e.code());
}
}
void impl_join(lua_State* L) {
try {
check_thread(L, 1)->join();
luaX_push_success(L);
} catch (const system_error& e) {
luaX_throw_failure(e.what(), e.code());
}
}
void impl_id(lua_State* L) {
thread* self = check_thread(L, 1);
std::ostringstream out;
out << self->get_id();
luaX_push(L, out.str());
}
}
void initialize_thread(lua_State* L) {
lua_newtable(L);
{
luaL_newmetatable(L, "dromozoa.multi.thread");
lua_pushvalue(L, -2);
luaX_set_field(L, -2, "__index");
luaX_set_field(L, -1, "__gc", impl_gc);
lua_pop(L, 1);
luaX_set_metafield(L, -1, "__call", impl_call);
luaX_set_field(L, -1, "detach", impl_detach);
luaX_set_field(L, -1, "join", impl_join);
luaX_set_field(L, -1, "id", impl_id);
}
luaX_set_field(L, -2, "thread");
}
}