diff options
Diffstat (limited to 'src/keeper.c')
-rw-r--r-- | src/keeper.c | 94 |
1 files changed, 77 insertions, 17 deletions
diff --git a/src/keeper.c b/src/keeper.c index 338f794..83ec8f3 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
@@ -128,20 +128,31 @@ static void fifo_peek( lua_State* L, keeper_fifo* fifo, int _count) | |||
128 | } | 128 | } |
129 | 129 | ||
130 | // in: fifo | 130 | // in: fifo |
131 | // out: pushes as many items as required on the stack (function assumes they exist in sufficient number) | 131 | // out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) |
132 | static void fifo_pop( lua_State* L, keeper_fifo* fifo, int _count) | 132 | static void fifo_pop( lua_State* L, keeper_fifo* fifo, int _count) |
133 | { | 133 | { |
134 | int fifo_idx = lua_gettop( L); // ... fifo | 134 | int fifo_idx = lua_gettop( L); // ... fifo |
135 | int i; | 135 | int i; |
136 | // each iteration pushes a value on the stack! | 136 | // each iteration pushes a value on the stack! |
137 | STACK_GROW( L, _count + 1); | 137 | STACK_GROW( L, _count + 2); |
138 | for( i = 0; i < _count; ++ i) | 138 | // skip first item, we will push it last |
139 | for( i = 1; i < _count; ++ i) | ||
139 | { | 140 | { |
140 | int at = fifo->first + i; | 141 | int const at = fifo->first + i; |
142 | // push item on the stack | ||
141 | lua_rawgeti( L, fifo_idx, at); // ... fifo val | 143 | lua_rawgeti( L, fifo_idx, at); // ... fifo val |
144 | // remove item from the fifo | ||
142 | lua_pushnil( L); // ... fifo val nil | 145 | lua_pushnil( L); // ... fifo val nil |
143 | lua_rawseti( L, fifo_idx, at); // ... fifo val | 146 | lua_rawseti( L, fifo_idx, at); // ... fifo val |
144 | } | 147 | } |
148 | // now process first item | ||
149 | { | ||
150 | int const at = fifo->first; | ||
151 | lua_rawgeti( L, fifo_idx, at); // ... fifo vals val | ||
152 | lua_pushnil( L); // ... fifo vals val nil | ||
153 | lua_rawseti( L, fifo_idx, at); // ... fifo vals val | ||
154 | lua_replace( L, fifo_idx); // ... vals | ||
155 | } | ||
145 | fifo->first += _count; | 156 | fifo->first += _count; |
146 | fifo->count -= _count; | 157 | fifo->count -= _count; |
147 | } | 158 | } |
@@ -172,6 +183,47 @@ static void push_table( lua_State* L, int idx) | |||
172 | STACK_END( L, 1); | 183 | STACK_END( L, 1); |
173 | } | 184 | } |
174 | 185 | ||
186 | int keeper_push_linda_storage( lua_State* L, void* ptr) | ||
187 | { | ||
188 | struct s_Keeper* K = keeper_acquire( ptr); | ||
189 | STACK_CHECK( K->L) | ||
190 | lua_pushlightuserdata( K->L, fifos_key); // fifos_key | ||
191 | lua_rawget( K->L, LUA_REGISTRYINDEX); // fifos | ||
192 | lua_pushlightuserdata( K->L, ptr); // fifos ud | ||
193 | lua_rawget( K->L, -2); // fifos storage | ||
194 | lua_remove( K->L, -2); // storage | ||
195 | if( !lua_istable( K->L, -1)) | ||
196 | { | ||
197 | lua_pop( K->L, 1); // | ||
198 | STACK_MID( K->L, 0); | ||
199 | return 0; | ||
200 | } | ||
201 | lua_pushnil( K->L); // storage nil | ||
202 | lua_newtable( L); // out | ||
203 | while( lua_next( K->L, -2)) // storage key fifo | ||
204 | { | ||
205 | keeper_fifo* fifo = prepare_fifo_access( K->L, -1); // storage key fifo | ||
206 | lua_pushvalue( K->L, -2); // storage key fifo key | ||
207 | luaG_inter_move( K->L, L, 1); // storage key fifo // out key | ||
208 | STACK_CHECK( L) | ||
209 | lua_newtable( L); // out key keyout | ||
210 | luaG_inter_move( K->L, L, 1); // storage key // out key keyout fifo | ||
211 | lua_pushinteger( L, fifo->first); // out key keyout fifo first | ||
212 | lua_setfield( L, -3, "first"); // out key keyout fifo | ||
213 | lua_pushinteger( L, fifo->count); // out key keyout fifo count | ||
214 | lua_setfield( L, -3, "count"); // out key keyout fifo | ||
215 | lua_pushinteger( L, fifo->limit); // out key keyout fifo limit | ||
216 | lua_setfield( L, -3, "limit"); // out key keyout fifo | ||
217 | lua_setfield( L, -2, "fifo"); // out key keyout | ||
218 | lua_rawset( L, -3); // out | ||
219 | STACK_END( L, 0) | ||
220 | } | ||
221 | lua_pop( K->L, 1); // | ||
222 | STACK_END( K->L, 0) | ||
223 | keeper_release( K); | ||
224 | return 1; | ||
225 | } | ||
226 | |||
175 | // in: linda_ud | 227 | // in: linda_ud |
176 | int keepercall_clear( lua_State* L) | 228 | int keepercall_clear( lua_State* L) |
177 | { | 229 | { |
@@ -223,7 +275,7 @@ int keepercall_send( lua_State* L) | |||
223 | } | 275 | } |
224 | 276 | ||
225 | // in: linda_ud, key [, key]? | 277 | // in: linda_ud, key [, key]? |
226 | // out: (val, key) or nothing | 278 | // out: (key, val) or nothing |
227 | int keepercall_receive( lua_State* L) | 279 | int keepercall_receive( lua_State* L) |
228 | { | 280 | { |
229 | int top = lua_gettop( L); | 281 | int top = lua_gettop( L); |
@@ -238,16 +290,17 @@ int keepercall_receive( lua_State* L) | |||
238 | fifo = prepare_fifo_access( L, -1); // fifos keys fifo | 290 | fifo = prepare_fifo_access( L, -1); // fifos keys fifo |
239 | if( fifo && fifo->count > 0) | 291 | if( fifo && fifo->count > 0) |
240 | { | 292 | { |
241 | fifo_pop( L, fifo, 1); // fifos keys fifo val | 293 | fifo_pop( L, fifo, 1); // fifos keys val |
242 | if( !lua_isnil( L, -1)) | 294 | if( !lua_isnil( L, -1)) |
243 | { | 295 | { |
244 | lua_replace( L, 1); // val keys fifo | 296 | lua_replace( L, 1); // val keys |
297 | lua_settop( L, i); // val keys key[i] | ||
245 | if( i != 2) | 298 | if( i != 2) |
246 | { | 299 | { |
247 | lua_pushvalue( L, i); // val keys fifo key[i] | 300 | lua_replace( L, 2); // val key keys |
248 | lua_replace( L, 2); // val key keys fifo | 301 | lua_settop( L, 2); // val key |
249 | } | 302 | } |
250 | lua_settop( L, 2); // val key | 303 | lua_insert( L, 1); // key, val |
251 | return 2; | 304 | return 2; |
252 | } | 305 | } |
253 | } | 306 | } |
@@ -266,16 +319,22 @@ int keepercall_receive_batched( lua_State* L) | |||
266 | keeper_fifo* fifo; | 319 | keeper_fifo* fifo; |
267 | int const max_count = (int) luaL_optinteger( L, 4, min_count); | 320 | int const max_count = (int) luaL_optinteger( L, 4, min_count); |
268 | lua_settop( L, 2); // ud key | 321 | lua_settop( L, 2); // ud key |
269 | push_table( L, 1); // ud key fifos | 322 | lua_insert( L, 1); // key ud |
270 | lua_replace( L, 1); // fifos key | 323 | push_table( L, 2); // key ud fifos |
271 | lua_rawget( L, -2); // fifos fifo | 324 | lua_remove( L, 2); // key fifos |
272 | lua_remove( L, 1); // fifo | 325 | lua_pushvalue( L, 1); // key fifos key |
273 | fifo = prepare_fifo_access( L, 1); // fifo | 326 | lua_rawget( L, 2); // key fifos fifo |
327 | lua_remove( L, 2); // key fifo | ||
328 | fifo = prepare_fifo_access( L, 2); // key fifo | ||
274 | if( fifo && fifo->count >= min_count) | 329 | if( fifo && fifo->count >= min_count) |
275 | { | 330 | { |
276 | fifo_pop( L, fifo, __min( max_count, fifo->count)); // fifo ... | 331 | fifo_pop( L, fifo, __min( max_count, fifo->count)); // key ... |
332 | } | ||
333 | else | ||
334 | { | ||
335 | lua_settop( L, 0); | ||
277 | } | 336 | } |
278 | return lua_gettop( L) - 1; | 337 | return lua_gettop( L); |
279 | } | 338 | } |
280 | else | 339 | else |
281 | { | 340 | { |
@@ -521,6 +580,7 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) | |||
521 | } | 580 | } |
522 | // call close_keepers at the very last as we want to be sure no thread is GCing after. | 581 | // call close_keepers at the very last as we want to be sure no thread is GCing after. |
523 | // (and therefore may perform linda object dereferencing after keepers are gone) | 582 | // (and therefore may perform linda object dereferencing after keepers are gone) |
583 | // problem: maybe on some platforms atexit() is called after DLL/so are unloaded... | ||
524 | atexit( atexit_close_keepers); | 584 | atexit( atexit_close_keepers); |
525 | return NULL; // ok | 585 | return NULL; // ok |
526 | } | 586 | } |