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
21#include "wrap_Channel.h"
22
23namespace love
24{
25namespace thread
26{
27
28Channel *luax_checkchannel(lua_State *L, int idx)
29{
30 return luax_checktype<Channel>(L, idx);
31}
32
33int w_Channel_push(lua_State *L)
34{
35 Channel *c = luax_checkchannel(L, 1);
36 luax_catchexcept(L, [&]() {
37 Variant var = Variant::fromLua(L, 2);
38 if (var.getType() == Variant::UNKNOWN)
39 luaL_argerror(L, 2, "boolean, number, string, love type, or table expected");
40 uint64 id = c->push(var);
41 lua_pushnumber(L, (lua_Number) id);
42 });
43 return 1;
44}
45
46int w_Channel_supply(lua_State *L)
47{
48 Channel *c = luax_checkchannel(L, 1);
49 bool result = false;
50 luax_catchexcept(L, [&]() {
51 Variant var = Variant::fromLua(L, 2);
52 if (var.getType() == Variant::UNKNOWN)
53 luaL_argerror(L, 2, "boolean, number, string, love type, or table expected");
54 if (lua_isnumber(L, 3))
55 result = c->supply(var, lua_tonumber(L, 3));
56 else
57 result = c->supply(var);
58 });
59
60 luax_pushboolean(L, result);
61 return 1;
62}
63
64int w_Channel_pop(lua_State *L)
65{
66 Channel *c = luax_checkchannel(L, 1);
67 Variant var;
68 if (c->pop(&var))
69 var.toLua(L);
70 else
71 lua_pushnil(L);
72 return 1;
73}
74
75int w_Channel_demand(lua_State *L)
76{
77 Channel *c = luax_checkchannel(L, 1);
78 Variant var;
79 bool result = false;
80
81 if (lua_isnumber(L, 2))
82 result = c->demand(&var, lua_tonumber(L, 2));
83 else
84 result = c->demand(&var);
85
86 if (result)
87 var.toLua(L);
88 else
89 lua_pushnil(L);
90 return 1;
91}
92
93int w_Channel_peek(lua_State *L)
94{
95 Channel *c = luax_checkchannel(L, 1);
96 Variant var;
97 if (c->peek(&var))
98 var.toLua(L);
99 else
100 lua_pushnil(L);
101 return 1;
102}
103
104int w_Channel_getCount(lua_State *L)
105{
106 Channel *c = luax_checkchannel(L, 1);
107 lua_pushnumber(L, c->getCount());
108 return 1;
109}
110
111int w_Channel_hasRead(lua_State *L)
112{
113 Channel *c = luax_checkchannel(L, 1);
114 uint64 id = (uint64) luaL_checknumber(L, 2);
115 luax_pushboolean(L, c->hasRead(id));
116 return 1;
117}
118
119int w_Channel_clear(lua_State *L)
120{
121 Channel *c = luax_checkchannel(L, 1);
122 c->clear();
123 return 0;
124}
125
126int w_Channel_performAtomic(lua_State *L)
127{
128 Channel *c = luax_checkchannel(L, 1);
129 luaL_checktype(L, 2, LUA_TFUNCTION);
130
131 // Pass this channel as an argument to the function.
132 lua_pushvalue(L, 1);
133 lua_insert(L, 3);
134
135 c->lockMutex();
136
137 // call the function, passing the channel as the first argument and any
138 // user-specified arguments after.
139 int numargs = lua_gettop(L) - 2;
140 int err = lua_pcall(L, numargs, LUA_MULTRET, 0);
141
142 c->unlockMutex();
143
144 // Unfortunately, this eats the stack trace, too bad.
145 if (err != 0)
146 return lua_error(L);
147
148 // The function and everything after it in the stack are eaten by the pcall,
149 // leaving only the Channel argument. Everything else is a return value.
150 return lua_gettop(L) - 1;
151}
152
153static const luaL_Reg w_Channel_functions[] =
154{
155 { "push", w_Channel_push },
156 { "supply", w_Channel_supply },
157 { "pop", w_Channel_pop },
158 { "demand", w_Channel_demand },
159 { "peek", w_Channel_peek },
160 { "getCount", w_Channel_getCount },
161 { "hasRead", w_Channel_hasRead },
162 { "clear", w_Channel_clear },
163 { "performAtomic", w_Channel_performAtomic },
164 { 0, 0 }
165};
166
167extern "C" int luaopen_channel(lua_State *L)
168{
169 return luax_register_type(L, &Channel::type, w_Channel_functions, nullptr);
170}
171
172} // thread
173} // love
174