diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2012-08-22 21:36:37 +0200 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2012-08-22 21:36:37 +0200 |
| commit | f0b1c6d629464c0a59ac78382d86f434e74c2162 (patch) | |
| tree | e6788f8e7c0e859cd5f8d9254a922e187d9e7938 /src | |
| parent | a9075ff6cf43e99cee994f5e77d0e1e54cb8dbac (diff) | |
| download | lanes-3.2.0.tar.gz lanes-3.2.0.tar.bz2 lanes-3.2.0.zip | |
lanes version 3.2.0v3.2.0
* keeper internals implemented in C instead of Lua for better performances
* fixed arguments checks in linda:limit() and linda:set()
Diffstat (limited to 'src')
| -rw-r--r-- | src/keeper.c | 390 | ||||
| -rw-r--r-- | src/keeper.h | 25 | ||||
| -rw-r--r-- | src/lanes-keeper.lua | 2 | ||||
| -rw-r--r-- | src/lanes.c | 31 |
4 files changed, 427 insertions, 21 deletions
diff --git a/src/keeper.c b/src/keeper.c index 444a98e..86c69e2 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | --[[ | 14 | --[[ |
| 15 | =============================================================================== | 15 | =============================================================================== |
| 16 | 16 | ||
| 17 | Copyright (C) 2011 Benoit Germain <bnt.germain@gmail.com> | 17 | Copyright (C) 2011-2012 Benoit Germain <bnt.germain@gmail.com> |
| 18 | 18 | ||
| 19 | Permission is hereby granted, free of charge, to any person obtaining a copy | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy |
| 20 | of this software and associated documentation files (the "Software"), to deal | 20 | of this software and associated documentation files (the "Software"), to deal |
| @@ -50,6 +50,374 @@ | |||
| 50 | #include "tools.h" | 50 | #include "tools.h" |
| 51 | #include "keeper.h" | 51 | #include "keeper.h" |
| 52 | 52 | ||
| 53 | #if KEEPER_MODEL == KEEPER_MODEL_C | ||
| 54 | //################################################################################### | ||
| 55 | // Keeper implementation | ||
| 56 | //################################################################################### | ||
| 57 | |||
| 58 | typedef struct | ||
| 59 | { | ||
| 60 | int first; | ||
| 61 | int count; | ||
| 62 | int limit; | ||
| 63 | } keeper_fifo; | ||
| 64 | |||
| 65 | // replaces the fifo ud by its uservalue on the stack | ||
| 66 | static keeper_fifo* prepare_fifo_access( lua_State* L, int idx) | ||
| 67 | { | ||
| 68 | keeper_fifo* fifo = (keeper_fifo*) lua_touserdata( L, idx); | ||
| 69 | if( fifo) | ||
| 70 | { | ||
| 71 | idx = lua_absindex( L, idx); | ||
| 72 | STACK_GROW( L, 1); | ||
| 73 | // we can replace the fifo userdata in the stack without fear of it being GCed, there are other references around | ||
| 74 | lua_getuservalue( L, idx); | ||
| 75 | lua_replace( L, idx); | ||
| 76 | } | ||
| 77 | return fifo; | ||
| 78 | } | ||
| 79 | |||
| 80 | // in: nothing | ||
| 81 | // out: { first = 1, count = 0, limit = -1} | ||
| 82 | static void fifo_new( lua_State* L) | ||
| 83 | { | ||
| 84 | keeper_fifo* fifo; | ||
| 85 | STACK_GROW( L, 2); | ||
| 86 | fifo = (keeper_fifo*) lua_newuserdata( L, sizeof( keeper_fifo)); | ||
| 87 | fifo->first = 1; | ||
| 88 | fifo->count = 0; | ||
| 89 | fifo->limit = -1; | ||
| 90 | lua_newtable( L); | ||
| 91 | lua_setuservalue( L, -2); | ||
| 92 | } | ||
| 93 | |||
| 94 | // in: expect fifo ... on top of the stack | ||
| 95 | // out: nothing, removes all pushed values on the stack | ||
| 96 | static void fifo_push( lua_State* L, keeper_fifo* fifo, int _count) | ||
| 97 | { | ||
| 98 | int idx = lua_gettop( L) - _count; | ||
| 99 | int start = fifo->first + fifo->count - 1; | ||
| 100 | int i; | ||
| 101 | // pop all additional arguments, storing them in the fifo | ||
| 102 | for( i = _count; i >= 1; -- i) | ||
| 103 | { | ||
| 104 | // store in the fifo the value at the top of the stack at the specified index, popping it from the stack | ||
| 105 | lua_rawseti( L, idx, start + i); | ||
| 106 | } | ||
| 107 | fifo->count += _count; | ||
| 108 | } | ||
| 109 | |||
| 110 | // in: fifo | ||
| 111 | // out: ...|nothing | ||
| 112 | // expects exactly 1 value on the stack! | ||
| 113 | // currently only called with a count of 1, but this may change in the future | ||
| 114 | // function assumes that there is enough data in the fifo to satisfy the request | ||
| 115 | static void fifo_peek( lua_State* L, keeper_fifo* fifo, int _count) | ||
| 116 | { | ||
| 117 | int i; | ||
| 118 | STACK_GROW( L, _count); | ||
| 119 | for( i = 0; i < _count; ++ i) | ||
| 120 | { | ||
| 121 | lua_rawgeti( L, 1, fifo->first + i); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | // in: fifo | ||
| 126 | // out: pushes as many items as required on the stack (function assumes they exist in sufficient number) | ||
| 127 | static void fifo_pop( lua_State* L, keeper_fifo* fifo, int _count) | ||
| 128 | { | ||
| 129 | int fifo_idx = lua_gettop( L); // ... fifo | ||
| 130 | int i; | ||
| 131 | // each iteration pushes a value on the stack! | ||
| 132 | STACK_GROW( L, _count + 1); | ||
| 133 | for( i = 0; i < _count; ++ i) | ||
| 134 | { | ||
| 135 | int at = fifo->first + i; | ||
| 136 | lua_rawgeti( L, fifo_idx, at); // ... fifo val | ||
| 137 | lua_pushnil( L); // ... fifo val nil | ||
| 138 | lua_rawseti( L, fifo_idx, at); // ... fifo val | ||
| 139 | } | ||
| 140 | fifo->first += _count; | ||
| 141 | fifo->count -= _count; | ||
| 142 | } | ||
| 143 | |||
| 144 | // in: linda_ud expected at *absolute* stack slot idx | ||
| 145 | // out: fifos[ud] | ||
| 146 | static void* const fifos_key = (void*) prepare_fifo_access; | ||
| 147 | static void push_table( lua_State* L, int idx) | ||
| 148 | { | ||
| 149 | STACK_GROW( L, 4); | ||
| 150 | STACK_CHECK( L) | ||
| 151 | idx = lua_absindex( L, idx); | ||
| 152 | lua_pushlightuserdata( L, fifos_key); // ud fifos_key | ||
| 153 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos | ||
| 154 | lua_pushvalue( L, idx); // ud fifos ud | ||
| 155 | lua_rawget( L, -2); // ud fifos fifos[ud] | ||
| 156 | STACK_MID( L, 2); | ||
| 157 | if( lua_isnil( L, -1)) | ||
| 158 | { | ||
| 159 | lua_pop( L, 1); // ud fifos | ||
| 160 | // add a new fifos table for this linda | ||
| 161 | lua_newtable( L); // ud fifos fifos[ud] | ||
| 162 | lua_pushvalue( L, idx); // ud fifos fifos[ud] ud | ||
| 163 | lua_pushvalue( L, -2); // ud fifos fifos[ud] ud fifos[ud] | ||
| 164 | lua_rawset( L, -4); // ud fifos fifos[ud] | ||
| 165 | } | ||
| 166 | lua_remove( L, -2); // ud fifos[ud] | ||
| 167 | STACK_END( L, 1); | ||
| 168 | } | ||
| 169 | |||
| 170 | // in: linda_ud | ||
| 171 | int keepercall_clear( lua_State* L) | ||
| 172 | { | ||
| 173 | STACK_GROW( L, 3); | ||
| 174 | lua_pushlightuserdata( L, fifos_key); // ud fifos_key | ||
| 175 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos | ||
| 176 | lua_pushvalue( L, 1); // ud fifos ud | ||
| 177 | lua_pushnil( L); // ud fifos ud nil | ||
| 178 | lua_rawset( L, -3); // ud fifos | ||
| 179 | lua_pop( L, 1); // ud | ||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | |||
| 184 | // in: linda_ud, key, ... | ||
| 185 | // out: true|false | ||
| 186 | int keepercall_send( lua_State* L) | ||
| 187 | { | ||
| 188 | keeper_fifo* fifo; | ||
| 189 | int n = lua_gettop( L) - 2; | ||
| 190 | push_table( L, 1); // ud key ... fifos | ||
| 191 | // get the fifo associated to this key in this linda, create it if it doesn't exist | ||
| 192 | lua_pushvalue( L, 2); // ud key ... fifos key | ||
| 193 | lua_rawget( L, -2); // ud key ... fifos fifo | ||
| 194 | if( lua_isnil( L, -1)) | ||
| 195 | { | ||
| 196 | lua_pop( L, 1); // ud key ... fifos | ||
| 197 | fifo_new( L); // ud key ... fifos fifo | ||
| 198 | lua_pushvalue( L, 2); // ud key ... fifos fifo key | ||
| 199 | lua_pushvalue( L, -2); // ud key ... fifos fifo key fifo | ||
| 200 | lua_rawset( L, -4); // ud key ... fifos fifo | ||
| 201 | } | ||
| 202 | lua_remove( L, -2); // ud key ... fifo | ||
| 203 | fifo = (keeper_fifo*) lua_touserdata( L, -1); | ||
| 204 | if( fifo->limit >= 0 && fifo->count + n > fifo->limit) | ||
| 205 | { | ||
| 206 | lua_settop( L, 0); // | ||
| 207 | lua_pushboolean( L, 0); // false | ||
| 208 | } | ||
| 209 | else | ||
| 210 | { | ||
| 211 | fifo = prepare_fifo_access( L, -1); | ||
| 212 | lua_replace( L, 2); // ud fifo ... | ||
| 213 | fifo_push( L, fifo, n); // ud fifo | ||
| 214 | lua_settop( L, 0); // | ||
| 215 | lua_pushboolean( L, 1); // true | ||
| 216 | } | ||
| 217 | return 1; | ||
| 218 | } | ||
| 219 | |||
| 220 | // in: linda_ud, key [, key]? | ||
| 221 | // out: (val, key) or nothing | ||
| 222 | int keepercall_receive( lua_State* L) | ||
| 223 | { | ||
| 224 | int top = lua_gettop( L); | ||
| 225 | int i; | ||
| 226 | keeper_fifo* fifo; | ||
| 227 | push_table( L, 1); // ud keys fifos | ||
| 228 | lua_replace( L, 1); // fifos keys | ||
| 229 | for( i = 2; i <= top; ++ i) | ||
| 230 | { | ||
| 231 | lua_pushvalue( L, i); // fifos keys key[i] | ||
| 232 | lua_rawget( L, 1); // fifos keys fifo | ||
| 233 | fifo = prepare_fifo_access( L, -1); // fifos keys fifo | ||
| 234 | if( fifo && fifo->count > 0) | ||
| 235 | { | ||
| 236 | fifo_pop( L, fifo, 1); // fifos keys fifo val | ||
| 237 | if( !lua_isnil( L, -1)) | ||
| 238 | { | ||
| 239 | lua_replace( L, 1); // val keys fifo | ||
| 240 | if( i != 2) | ||
| 241 | { | ||
| 242 | lua_pushvalue( L, i); // val keys fifo key[i] | ||
| 243 | lua_replace( L, 2); // val key keys fifo | ||
| 244 | } | ||
| 245 | lua_settop( L, 2); // val key | ||
| 246 | return 2; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | lua_settop( L, top); // data keys | ||
| 250 | } | ||
| 251 | // nothing to receive | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | //in: linda_ud key mincount [maxcount] | ||
| 256 | int keepercall_receive_batched( lua_State* L) | ||
| 257 | { | ||
| 258 | int const min_count = (int) lua_tointeger( L, 3); | ||
| 259 | if( min_count > 0) | ||
| 260 | { | ||
| 261 | keeper_fifo* fifo; | ||
| 262 | int const max_count = (int) luaL_optinteger( L, 4, min_count); | ||
| 263 | lua_settop( L, 2); // ud key | ||
| 264 | push_table( L, 1); // ud key fifos | ||
| 265 | lua_replace( L, 1); // fifos key | ||
| 266 | lua_rawget( L, -2); // fifos fifo | ||
| 267 | lua_remove( L, 1); // fifo | ||
| 268 | fifo = prepare_fifo_access( L, 1); // fifo | ||
| 269 | if( fifo && fifo->count >= min_count) | ||
| 270 | { | ||
| 271 | fifo_pop( L, fifo, min( max_count, fifo->count)); // fifo ... | ||
| 272 | } | ||
| 273 | return lua_gettop( L) - 1; | ||
| 274 | } | ||
| 275 | else | ||
| 276 | { | ||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | // in: linda_ud key n | ||
| 282 | // out: nothing | ||
| 283 | int keepercall_limit( lua_State* L) | ||
| 284 | { | ||
| 285 | keeper_fifo* fifo; | ||
| 286 | int limit = (int) lua_tointeger( L, 3); | ||
| 287 | push_table( L, 1); // ud key n fifos | ||
| 288 | lua_replace( L, 1); // fifos key n | ||
| 289 | lua_pop( L, 1); // fifos key | ||
| 290 | lua_pushvalue( L, -1); // fifos key key | ||
| 291 | lua_rawget( L, -3); // fifos key fifo | ||
| 292 | fifo = (keeper_fifo*) lua_touserdata( L, -1); | ||
| 293 | if( !fifo) | ||
| 294 | { | ||
| 295 | lua_pop( L, 1); // fifos key | ||
| 296 | fifo_new( L); // fifos key fifo | ||
| 297 | fifo = (keeper_fifo*) lua_touserdata( L, -1); | ||
| 298 | lua_rawset( L, -3); // fifos | ||
| 299 | } | ||
| 300 | fifo->limit = limit; | ||
| 301 | return 0; | ||
| 302 | } | ||
| 303 | |||
| 304 | //in: linda_ud key [val] | ||
| 305 | int keepercall_set( lua_State* L) | ||
| 306 | { | ||
| 307 | // make sure we have a value on the stack | ||
| 308 | if( lua_gettop( L) == 2) | ||
| 309 | { | ||
| 310 | lua_pushnil( L); | ||
| 311 | } | ||
| 312 | push_table( L, 1); // ud key val fifos | ||
| 313 | lua_replace( L, 1); // fifos key val | ||
| 314 | if( !lua_isnil( L, 3)) // replace contents stored at the specified key? | ||
| 315 | { | ||
| 316 | keeper_fifo* fifo; | ||
| 317 | fifo_new( L); // fifos key val fifo | ||
| 318 | lua_pushvalue( L, 2); // fifos key val fifo key | ||
| 319 | lua_pushvalue( L, -2); // fifos key val fifo key fifo | ||
| 320 | lua_rawset( L, 1); // fifos key val fifo | ||
| 321 | fifo = prepare_fifo_access( L, -1); | ||
| 322 | lua_insert( L, -2); // fifos key fifo val | ||
| 323 | fifo_push( L, fifo, 1); // fifos key fifo | ||
| 324 | } | ||
| 325 | else | ||
| 326 | { | ||
| 327 | // val == nil => stack contents: fifos key nil => remove the fifo associated with the current key | ||
| 328 | lua_rawset( L, 1); // fifos | ||
| 329 | } | ||
| 330 | return 0; | ||
| 331 | } | ||
| 332 | |||
| 333 | // in: linda_ud key | ||
| 334 | int keepercall_get( lua_State* L) | ||
| 335 | { | ||
| 336 | keeper_fifo* fifo; | ||
| 337 | push_table( L, 1); // ud key fifos | ||
| 338 | lua_replace( L, 1); // fifos key | ||
| 339 | lua_rawget( L, 1); // fifos fifo | ||
| 340 | fifo = prepare_fifo_access( L, -1); // fifos fifo | ||
| 341 | if( fifo && fifo->count > 0) | ||
| 342 | { | ||
| 343 | lua_remove( L, 1); // fifo | ||
| 344 | // read one value off the fifo | ||
| 345 | fifo_peek( L, fifo, 1); // fifo ... | ||
| 346 | return 1; | ||
| 347 | } | ||
| 348 | // no fifo was ever registered for this key, or it is empty | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | // in: linda_ud [, key [, ...]] | ||
| 353 | int keepercall_count( lua_State* L) | ||
| 354 | { | ||
| 355 | int top; | ||
| 356 | push_table( L, 1); // ud keys fifos | ||
| 357 | switch( lua_gettop( L)) | ||
| 358 | { | ||
| 359 | // no key is specified: return a table giving the count of all known keys | ||
| 360 | case 2: // ud fifos | ||
| 361 | lua_newtable( L); // ud fifos out | ||
| 362 | lua_replace( L, 1); // out fifos | ||
| 363 | lua_pushnil( L); // out fifos nil | ||
| 364 | while( lua_next( L, 2)) // out fifos key fifo | ||
| 365 | { | ||
| 366 | keeper_fifo* fifo = prepare_fifo_access( L, -1); // out fifos key fifo | ||
| 367 | lua_pop( L, 1); // out fifos key | ||
| 368 | lua_pushvalue( L, -1); // out fifos key key | ||
| 369 | lua_pushinteger( L, fifo->count); // out fifos key key count | ||
| 370 | lua_rawset( L, -5); // out fifos key | ||
| 371 | } | ||
| 372 | lua_pop( L, 1); // out | ||
| 373 | break; | ||
| 374 | |||
| 375 | // 1 key is specified: return its count | ||
| 376 | case 3: // ud key fifos | ||
| 377 | { | ||
| 378 | keeper_fifo* fifo; | ||
| 379 | lua_replace( L, 1); // fifos key | ||
| 380 | lua_rawget( L, -2); // fifos fifo | ||
| 381 | fifo = prepare_fifo_access( L, -1); // fifos fifo | ||
| 382 | lua_pushinteger( L, fifo->count); // fifos fifo count | ||
| 383 | lua_replace( L, -3); // count fifo | ||
| 384 | lua_pop( L, 1); // count | ||
| 385 | } | ||
| 386 | break; | ||
| 387 | |||
| 388 | // a variable number of keys is specified: return a table of their counts | ||
| 389 | default: // ud keys fifos | ||
| 390 | lua_newtable( L); // ud keys fifos out | ||
| 391 | lua_replace( L, 1); // out keys fifos | ||
| 392 | // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable | ||
| 393 | lua_insert( L, 2); // out fifos keys | ||
| 394 | while( (top = lua_gettop( L)) > 2) | ||
| 395 | { | ||
| 396 | keeper_fifo* fifo; | ||
| 397 | lua_pushvalue( L, -1); // out fifos keys key | ||
| 398 | lua_rawget( L, 2); // out fifos keys fifo | ||
| 399 | fifo = prepare_fifo_access( L, -1); // out fifos keys fifo | ||
| 400 | lua_pop( L, 1); // out fifos keys | ||
| 401 | if( fifo) | ||
| 402 | { | ||
| 403 | lua_pushinteger( L, fifo->count); // out fifos keys count | ||
| 404 | lua_rawset( L, 1); // out fifos keys | ||
| 405 | } | ||
| 406 | else | ||
| 407 | { | ||
| 408 | lua_pop( L, 1); // out fifos keys | ||
| 409 | } | ||
| 410 | } | ||
| 411 | lua_pop( L, 1); // out | ||
| 412 | } | ||
| 413 | return 1; | ||
| 414 | } | ||
| 415 | #endif // KEEPER_MODEL == KEEPER_MODEL_C | ||
| 416 | |||
| 417 | //################################################################################### | ||
| 418 | // Keeper API, accessed from linda methods | ||
| 419 | //################################################################################### | ||
| 420 | |||
| 53 | /*---=== Keeper states ===--- | 421 | /*---=== Keeper states ===--- |
| 54 | */ | 422 | */ |
| 55 | 423 | ||
| @@ -115,6 +483,14 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) | |||
| 115 | lua_concat( K, 2); | 483 | lua_concat( K, 2); |
| 116 | lua_setglobal( K, "decoda_name"); | 484 | lua_setglobal( K, "decoda_name"); |
| 117 | 485 | ||
| 486 | #if KEEPER_MODEL == KEEPER_MODEL_C | ||
| 487 | // create the fifos table in the keeper state | ||
| 488 | lua_pushlightuserdata( K, fifos_key); | ||
| 489 | lua_newtable( K); | ||
| 490 | lua_rawset( K, LUA_REGISTRYINDEX); | ||
| 491 | #endif // KEEPER_MODEL == KEEPER_MODEL_C | ||
| 492 | |||
| 493 | #if KEEPER_MODEL == KEEPER_MODEL_LUA | ||
| 118 | // use package.loaders[2] to find keeper microcode | 494 | // use package.loaders[2] to find keeper microcode |
| 119 | lua_getglobal( K, "package"); // package | 495 | lua_getglobal( K, "package"); // package |
| 120 | lua_getfield( K, -1, "loaders"); // package package.loaders | 496 | lua_getfield( K, -1, "loaders"); // package package.loaders |
| @@ -132,6 +508,7 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) | |||
| 132 | } // package package.loaders | 508 | } // package package.loaders |
| 133 | STACK_MID( K, 2); | 509 | STACK_MID( K, 2); |
| 134 | lua_pop( K, 2); | 510 | lua_pop( K, 2); |
| 511 | #endif // KEEPER_MODEL == KEEPER_MODEL_LUA | ||
| 135 | STACK_END( K, 0) | 512 | STACK_END( K, 0) |
| 136 | MUTEX_INIT( &GKeepers[i].lock_); | 513 | MUTEX_INIT( &GKeepers[i].lock_); |
| 137 | GKeepers[i].L = K; | 514 | GKeepers[i].L = K; |
| @@ -207,7 +584,7 @@ struct s_Keeper *keeper_acquire( const void *ptr) | |||
| 207 | * | 584 | * |
| 208 | * Pointers are often aligned by 8 or so - ignore the low order bits | 585 | * Pointers are often aligned by 8 or so - ignore the low order bits |
| 209 | */ | 586 | */ |
| 210 | unsigned int i= ((unsigned long)(ptr) >> 3) % GNbKeepers; | 587 | unsigned int i= ((uintptr_t)(ptr) >> 3) % GNbKeepers; |
| 211 | struct s_Keeper *K= &GKeepers[i]; | 588 | struct s_Keeper *K= &GKeepers[i]; |
| 212 | 589 | ||
| 213 | MUTEX_LOCK( &K->lock_); | 590 | MUTEX_LOCK( &K->lock_); |
| @@ -259,16 +636,15 @@ void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel | |||
| 259 | * | 636 | * |
| 260 | * Returns: number of return values (pushed to 'L') or -1 in case of error | 637 | * Returns: number of return values (pushed to 'L') or -1 in case of error |
| 261 | */ | 638 | */ |
| 262 | int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index) | 639 | int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, uint_t starting_index) |
| 263 | { | 640 | { |
| 264 | int const args = starting_index ? (lua_gettop(L) - starting_index +1) : 0; | 641 | int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0; |
| 265 | int const Ktos = lua_gettop(K); | 642 | int const Ktos = lua_gettop( K); |
| 266 | int retvals = -1; | 643 | int retvals = -1; |
| 267 | 644 | ||
| 268 | STACK_GROW( K, 2); | 645 | STACK_GROW( K, 2); |
| 269 | 646 | ||
| 270 | lua_getglobal( K, func_name); | 647 | PUSH_KEEPER_FUNC( K, _func); |
| 271 | ASSERT_L( lua_isfunction(K, -1)); | ||
| 272 | 648 | ||
| 273 | lua_pushlightuserdata( K, linda); | 649 | lua_pushlightuserdata( K, linda); |
| 274 | 650 | ||
diff --git a/src/keeper.h b/src/keeper.h index 6c4c6f9..a0ea8c5 100644 --- a/src/keeper.h +++ b/src/keeper.h | |||
| @@ -13,7 +13,30 @@ void populate_keepers( lua_State *L); | |||
| 13 | struct s_Keeper *keeper_acquire( const void *ptr); | 13 | struct s_Keeper *keeper_acquire( const void *ptr); |
| 14 | void keeper_release( struct s_Keeper *K); | 14 | void keeper_release( struct s_Keeper *K); |
| 15 | void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); | 15 | void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); |
| 16 | int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index); | ||
| 17 | 16 | ||
| 17 | #define KEEPER_MODEL_LUA 1 | ||
| 18 | #define KEEPER_MODEL_C 2 | ||
| 19 | #define KEEPER_MODEL KEEPER_MODEL_C | ||
| 20 | |||
| 21 | #if KEEPER_MODEL == KEEPER_MODEL_LUA | ||
| 22 | typedef char const* keeper_api_t; | ||
| 23 | #define KEEPER_API( _op) #_op | ||
| 24 | #define PUSH_KEEPER_FUNC( K, _api) lua_getglobal( K, _api) | ||
| 25 | #elif KEEPER_MODEL == KEEPER_MODEL_C | ||
| 26 | typedef lua_CFunction keeper_api_t; | ||
| 27 | #define KEEPER_API( _op) keepercall_ ## _op | ||
| 28 | #define PUSH_KEEPER_FUNC lua_pushcfunction | ||
| 29 | // lua_Cfunctions to run inside a keeper state (formerly implemented in Lua) | ||
| 30 | int keepercall_clear( lua_State* L); | ||
| 31 | int keepercall_send( lua_State* L); | ||
| 32 | int keepercall_receive( lua_State* L); | ||
| 33 | int keepercall_receive_batched( lua_State* L); | ||
| 34 | int keepercall_limit( lua_State* L); | ||
| 35 | int keepercall_get( lua_State* L); | ||
| 36 | int keepercall_set( lua_State* L); | ||
| 37 | int keepercall_count( lua_State* L); | ||
| 38 | #endif // KEEPER_MODEL | ||
| 39 | |||
| 40 | int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, uint_t starting_index); | ||
| 18 | 41 | ||
| 19 | #endif // __keeper_h__ \ No newline at end of file | 42 | #endif // __keeper_h__ \ No newline at end of file |
diff --git a/src/lanes-keeper.lua b/src/lanes-keeper.lua index 1f17599..b07d6a9 100644 --- a/src/lanes-keeper.lua +++ b/src/lanes-keeper.lua | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | -- KEEPER.LUA | 2 | -- KEEPER.LUA |
| 3 | -- | 3 | -- |
| 4 | -- Keeper state logic | 4 | -- Keeper state logic |
| 5 | -- DEPRECATED BY THE EQUIVALENT C IMPLEMENTATION, KEPT FOR REFERENCE ONLY | ||
| 6 | -- SHOULD NOT BE PART OF THE INSTALLATION ANYMORE | ||
| 5 | -- | 7 | -- |
| 6 | -- This code is read in for each "keeper state", which are the hidden, inter- | 8 | -- This code is read in for each "keeper state", which are the hidden, inter- |
| 7 | -- mediate data stores used by Lanes inter-state communication objects. | 9 | -- mediate data stores used by Lanes inter-state communication objects. |
diff --git a/src/lanes.c b/src/lanes.c index 8f5768f..9f455b2 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
| @@ -51,7 +51,7 @@ | |||
| 51 | * ... | 51 | * ... |
| 52 | */ | 52 | */ |
| 53 | 53 | ||
| 54 | char const* VERSION = "3.1.6"; | 54 | char const* VERSION = "3.2.0"; |
| 55 | 55 | ||
| 56 | /* | 56 | /* |
| 57 | =============================================================================== | 57 | =============================================================================== |
| @@ -309,7 +309,7 @@ LUAG_FUNC( linda_send) | |||
| 309 | for( ;;) | 309 | for( ;;) |
| 310 | { | 310 | { |
| 311 | STACK_MID(KL, 0) | 311 | STACK_MID(KL, 0) |
| 312 | pushed = keeper_call( KL, "send", L, linda, key_i); | 312 | pushed = keeper_call( KL, KEEPER_API( send), L, linda, key_i); |
| 313 | if( pushed < 0) | 313 | if( pushed < 0) |
| 314 | { | 314 | { |
| 315 | break; | 315 | break; |
| @@ -410,7 +410,7 @@ LUAG_FUNC( linda_receive) | |||
| 410 | struct s_Linda *linda = lua_toLinda( L, 1); | 410 | struct s_Linda *linda = lua_toLinda( L, 1); |
| 411 | int pushed, expected_pushed_min, expected_pushed_max; | 411 | int pushed, expected_pushed_min, expected_pushed_max; |
| 412 | bool_t cancel = FALSE; | 412 | bool_t cancel = FALSE; |
| 413 | char *keeper_receive; | 413 | keeper_api_t keeper_receive; |
| 414 | 414 | ||
| 415 | time_d timeout = -1.0; | 415 | time_d timeout = -1.0; |
| 416 | uint_t key_i = 2; | 416 | uint_t key_i = 2; |
| @@ -440,7 +440,7 @@ LUAG_FUNC( linda_receive) | |||
| 440 | // make sure the keys are of a valid type | 440 | // make sure the keys are of a valid type |
| 441 | check_key_types( L, key_i, key_i); | 441 | check_key_types( L, key_i, key_i); |
| 442 | // receive multiple values from a single slot | 442 | // receive multiple values from a single slot |
| 443 | keeper_receive = "receive_batched"; | 443 | keeper_receive = KEEPER_API( receive_batched); |
| 444 | // we expect a user-defined amount of return value | 444 | // we expect a user-defined amount of return value |
| 445 | expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1); | 445 | expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1); |
| 446 | expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min); | 446 | expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min); |
| @@ -454,7 +454,7 @@ LUAG_FUNC( linda_receive) | |||
| 454 | // make sure the keys are of a valid type | 454 | // make sure the keys are of a valid type |
| 455 | check_key_types( L, key_i, lua_gettop( L)); | 455 | check_key_types( L, key_i, lua_gettop( L)); |
| 456 | // receive a single value, checking multiple slots | 456 | // receive a single value, checking multiple slots |
| 457 | keeper_receive = "receive"; | 457 | keeper_receive = KEEPER_API( receive); |
| 458 | // we expect a single (value, key) pair of returned values | 458 | // we expect a single (value, key) pair of returned values |
| 459 | expected_pushed_min = expected_pushed_max = 2; | 459 | expected_pushed_min = expected_pushed_max = 2; |
| 460 | } | 460 | } |
| @@ -558,6 +558,7 @@ LUAG_FUNC( linda_set) | |||
| 558 | struct s_Linda *linda = lua_toLinda( L, 1); | 558 | struct s_Linda *linda = lua_toLinda( L, 1); |
| 559 | bool_t has_value = !lua_isnil( L, 3); | 559 | bool_t has_value = !lua_isnil( L, 3); |
| 560 | luaL_argcheck( L, linda, 1, "expected a linda object!"); | 560 | luaL_argcheck( L, linda, 1, "expected a linda object!"); |
| 561 | luaL_argcheck( L, lua_gettop( L) <= 3, 4, "too many arguments"); | ||
| 561 | 562 | ||
| 562 | // make sure the key is of a valid type | 563 | // make sure the key is of a valid type |
| 563 | check_key_types( L, 2, 2); | 564 | check_key_types( L, 2, 2); |
| @@ -566,7 +567,7 @@ LUAG_FUNC( linda_set) | |||
| 566 | int pushed; | 567 | int pushed; |
| 567 | struct s_Keeper *K = keeper_acquire( linda); | 568 | struct s_Keeper *K = keeper_acquire( linda); |
| 568 | // no nil->sentinel toggling, we really clear the linda contents for the given key with a set() | 569 | // no nil->sentinel toggling, we really clear the linda contents for the given key with a set() |
| 569 | pushed = keeper_call( K->L, "set", L, linda, 2); | 570 | pushed = keeper_call( K->L, KEEPER_API( set), L, linda, 2); |
| 570 | if( pushed >= 0) // no error? | 571 | if( pushed >= 0) // no error? |
| 571 | { | 572 | { |
| 572 | ASSERT_L( pushed == 0); | 573 | ASSERT_L( pushed == 0); |
| @@ -606,7 +607,7 @@ LUAG_FUNC( linda_count) | |||
| 606 | 607 | ||
| 607 | { | 608 | { |
| 608 | struct s_Keeper *K = keeper_acquire( linda); | 609 | struct s_Keeper *K = keeper_acquire( linda); |
| 609 | pushed = keeper_call( K->L, "count", L, linda, 2); | 610 | pushed = keeper_call( K->L, KEEPER_API( count), L, linda, 2); |
| 610 | keeper_release( K); | 611 | keeper_release( K); |
| 611 | if( pushed < 0) | 612 | if( pushed < 0) |
| 612 | { | 613 | { |
| @@ -634,7 +635,7 @@ LUAG_FUNC( linda_get) | |||
| 634 | 635 | ||
| 635 | { | 636 | { |
| 636 | struct s_Keeper *K = keeper_acquire( linda); | 637 | struct s_Keeper *K = keeper_acquire( linda); |
| 637 | pushed = keeper_call( K->L, "get", L, linda, 2); | 638 | pushed = keeper_call( K->L, KEEPER_API( get), L, linda, 2); |
| 638 | ASSERT_L( pushed==0 || pushed==1 ); | 639 | ASSERT_L( pushed==0 || pushed==1 ); |
| 639 | if( pushed > 0) | 640 | if( pushed > 0) |
| 640 | { | 641 | { |
| @@ -659,15 +660,19 @@ LUAG_FUNC( linda_get) | |||
| 659 | */ | 660 | */ |
| 660 | LUAG_FUNC( linda_limit) | 661 | LUAG_FUNC( linda_limit) |
| 661 | { | 662 | { |
| 662 | struct s_Linda *linda= lua_toLinda( L, 1 ); | 663 | struct s_Linda* linda= lua_toLinda( L, 1 ); |
| 663 | 664 | ||
| 664 | luaL_argcheck( L, linda, 1, "expected a linda object!"); | 665 | luaL_argcheck( L, linda, 1, "expected a linda object!"); |
| 666 | // make sure we got a key and a limit | ||
| 667 | luaL_argcheck( L, lua_gettop( L) == 3, 2, "wrong number of arguments"); | ||
| 668 | // make sure we got a numeric limit | ||
| 669 | luaL_checknumber( L, 3); | ||
| 665 | // make sure the key is of a valid type | 670 | // make sure the key is of a valid type |
| 666 | check_key_types( L, 2, 2); | 671 | check_key_types( L, 2, 2); |
| 667 | 672 | ||
| 668 | { | 673 | { |
| 669 | struct s_Keeper *K = keeper_acquire( linda); | 674 | struct s_Keeper* K = keeper_acquire( linda); |
| 670 | int pushed = keeper_call( K->L, "limit", L, linda, 2); | 675 | int pushed = keeper_call( K->L, KEEPER_API( limit), L, linda, 2); |
| 671 | ASSERT_L( pushed <= 0); // either error or no return values | 676 | ASSERT_L( pushed <= 0); // either error or no return values |
| 672 | keeper_release( K); | 677 | keeper_release( K); |
| 673 | // must trigger error after keeper state has been released | 678 | // must trigger error after keeper state has been released |
| @@ -825,8 +830,8 @@ static void linda_id( lua_State *L, char const * const which) | |||
| 825 | K= keeper_acquire(s); | 830 | K= keeper_acquire(s); |
| 826 | if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup) | 831 | if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup) |
| 827 | { | 832 | { |
| 828 | keeper_call( K->L, "clear", L, s, 0 ); | 833 | keeper_call( K->L, KEEPER_API( clear), L, s, 0 ); |
| 829 | keeper_release(K); | 834 | keeper_release( K); |
| 830 | } | 835 | } |
| 831 | 836 | ||
| 832 | /* There aren't any lanes waiting on these lindas, since all proxies | 837 | /* There aren't any lanes waiting on these lindas, since all proxies |
