diff options
-rw-r--r-- | src/keeper.cpp | 98 | ||||
-rw-r--r-- | src/lanes.cpp | 7 | ||||
-rw-r--r-- | src/macros_and_utils.h | 6 |
3 files changed, 59 insertions, 52 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp index e0a9fdc..cb2b0a9 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -60,7 +60,8 @@ class keeper_fifo | |||
60 | int count{ 0 }; | 60 | int count{ 0 }; |
61 | int limit{ -1 }; | 61 | int limit{ -1 }; |
62 | 62 | ||
63 | static void* operator new(size_t size_, lua_State* L) noexcept { return lua_newuserdatauv(L, size_, 1); } | 63 | // a fifo full userdata has one uservalue, the table that holds the actual fifo contents |
64 | static void* operator new(size_t size_, lua_State* L) noexcept { return lua_newuserdatauv<keeper_fifo>(L, 1); } | ||
64 | // always embedded somewhere else or "in-place constructed" as a full userdata | 65 | // always embedded somewhere else or "in-place constructed" as a full userdata |
65 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 66 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
66 | static void operator delete(void* p_, lua_State* L){ ASSERT_L(!"should never be called") }; | 67 | static void operator delete(void* p_, lua_State* L){ ASSERT_L(!"should never be called") }; |
@@ -94,16 +95,16 @@ static keeper_fifo* prepare_fifo_access(lua_State* L, int idx_) | |||
94 | 95 | ||
95 | // in: nothing | 96 | // in: nothing |
96 | // out: { first = 1, count = 0, limit = -1} | 97 | // out: { first = 1, count = 0, limit = -1} |
97 | static void fifo_new(lua_State* L) | 98 | static keeper_fifo* fifo_new(lua_State* L) |
98 | { | 99 | { |
99 | STACK_GROW(L, 2); | 100 | STACK_GROW(L, 2); |
100 | STACK_CHECK_START_REL(L, 0); | 101 | STACK_CHECK_START_REL(L, 0); |
101 | // a fifo full userdata has one uservalue, the table that holds the actual fifo contents | 102 | keeper_fifo* const fifo{ new (L) keeper_fifo{} }; |
102 | [[maybe_unused]] keeper_fifo* const fifo{ new (L) keeper_fifo{} }; | ||
103 | STACK_CHECK(L, 1); | 103 | STACK_CHECK(L, 1); |
104 | lua_newtable(L); | 104 | lua_newtable(L); |
105 | lua_setiuservalue(L, -2, CONTENTS_TABLE); | 105 | lua_setiuservalue(L, -2, CONTENTS_TABLE); |
106 | STACK_CHECK(L, 1); | 106 | STACK_CHECK(L, 1); |
107 | return fifo; | ||
107 | } | 108 | } |
108 | 109 | ||
109 | // ################################################################################################## | 110 | // ################################################################################################## |
@@ -145,7 +146,8 @@ static void fifo_peek(lua_State* L, keeper_fifo* fifo_, int count_) | |||
145 | // out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) | 146 | // out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) |
146 | static void fifo_pop( lua_State* L, keeper_fifo* fifo_, int count_) | 147 | static void fifo_pop( lua_State* L, keeper_fifo* fifo_, int count_) |
147 | { | 148 | { |
148 | int const fifo_idx = lua_gettop(L); // ... fifo | 149 | ASSERT_L(lua_istable(L, -1)); |
150 | int const fifo_idx{ lua_gettop(L) }; // ... fifotbl | ||
149 | // each iteration pushes a value on the stack! | 151 | // each iteration pushes a value on the stack! |
150 | STACK_GROW(L, count_ + 2); | 152 | STACK_GROW(L, count_ + 2); |
151 | // skip first item, we will push it last | 153 | // skip first item, we will push it last |
@@ -153,21 +155,22 @@ static void fifo_pop( lua_State* L, keeper_fifo* fifo_, int count_) | |||
153 | { | 155 | { |
154 | int const at{ fifo_->first + i }; | 156 | int const at{ fifo_->first + i }; |
155 | // push item on the stack | 157 | // push item on the stack |
156 | lua_rawgeti(L, fifo_idx, at); // ... fifo val | 158 | lua_rawgeti(L, fifo_idx, at); // ... fifotbl val |
157 | // remove item from the fifo | 159 | // remove item from the fifo |
158 | lua_pushnil(L); // ... fifo val nil | 160 | lua_pushnil(L); // ... fifotbl val nil |
159 | lua_rawseti(L, fifo_idx, at); // ... fifo val | 161 | lua_rawseti(L, fifo_idx, at); // ... fifotbl val |
160 | } | 162 | } |
161 | // now process first item | 163 | // now process first item |
162 | { | 164 | { |
163 | int const at{ fifo_->first }; | 165 | int const at{ fifo_->first }; |
164 | lua_rawgeti(L, fifo_idx, at); // ... fifo vals val | 166 | lua_rawgeti(L, fifo_idx, at); // ... fifotbl vals val |
165 | lua_pushnil(L); // ... fifo vals val nil | 167 | lua_pushnil(L); // ... fifotbl vals val nil |
166 | lua_rawseti(L, fifo_idx, at); // ... fifo vals val | 168 | lua_rawseti(L, fifo_idx, at); // ... fifotbl vals val |
167 | lua_replace(L, fifo_idx); // ... vals | 169 | lua_replace(L, fifo_idx); // ... vals |
168 | } | 170 | } |
171 | |||
172 | // avoid ever-growing indexes by resetting each time we detect the fifo is empty | ||
169 | { | 173 | { |
170 | // avoid ever-growing indexes by resetting each time we detect the fifo is empty | ||
171 | int const new_count{ fifo_->count - count_ }; | 174 | int const new_count{ fifo_->count - count_ }; |
172 | fifo_->first = (new_count == 0) ? 1 : (fifo_->first + count_); | 175 | fifo_->first = (new_count == 0) ? 1 : (fifo_->first + count_); |
173 | fifo_->count = new_count; | 176 | fifo_->count = new_count; |
@@ -228,21 +231,21 @@ int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t m | |||
228 | lua_newtable(L); // out | 231 | lua_newtable(L); // out |
229 | while( lua_next(KL, -2)) // storage key fifo | 232 | while( lua_next(KL, -2)) // storage key fifo |
230 | { | 233 | { |
231 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifo | 234 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl |
232 | lua_pushvalue(KL, -2); // storage key fifo key | 235 | lua_pushvalue(KL, -2); // storage key fifotbl key |
233 | luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key fifo // out key | 236 | luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key fifotbl // out key |
234 | STACK_CHECK(L, 2); | 237 | STACK_CHECK(L, 2); |
235 | lua_newtable(L); // out key keyout | 238 | lua_newtable(L); // out key keyout |
236 | luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo | 239 | luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifotbl |
237 | lua_pushinteger(L, fifo->first); // out key keyout fifo first | 240 | lua_pushinteger(L, fifo->first); // out key keyout fifotbl first |
238 | STACK_CHECK(L, 5); | 241 | STACK_CHECK(L, 5); |
239 | lua_setfield(L, -3, "first"); // out key keyout fifo | 242 | lua_setfield(L, -3, "first"); // out key keyout fifotbl |
240 | lua_pushinteger(L, fifo->count); // out key keyout fifo count | 243 | lua_pushinteger(L, fifo->count); // out key keyout fifobtl count |
241 | STACK_CHECK(L, 5); | 244 | STACK_CHECK(L, 5); |
242 | lua_setfield(L, -3, "count"); // out key keyout fifo | 245 | lua_setfield(L, -3, "count"); // out key keyout fifotbl |
243 | lua_pushinteger(L, fifo->limit); // out key keyout fifo limit | 246 | lua_pushinteger(L, fifo->limit); // out key keyout fifotbl limit |
244 | STACK_CHECK(L, 5); | 247 | STACK_CHECK(L, 5); |
245 | lua_setfield(L, -3, "limit"); // out key keyout fifo | 248 | lua_setfield(L, -3, "limit"); // out key keyout fifotbl |
246 | lua_setfield(L, -2, "fifo"); // out key keyout | 249 | lua_setfield(L, -2, "fifo"); // out key keyout |
247 | lua_rawset(L, -3); // out | 250 | lua_rawset(L, -3); // out |
248 | STACK_CHECK(L, 1); | 251 | STACK_CHECK(L, 1); |
@@ -297,9 +300,9 @@ int keepercall_send(lua_State* L) | |||
297 | } | 300 | } |
298 | else | 301 | else |
299 | { | 302 | { |
300 | fifo = prepare_fifo_access(L, -1); | 303 | fifo = prepare_fifo_access(L, -1); // ud fifotbl |
301 | lua_replace(L, 2); // ud fifo ... | 304 | lua_replace(L, 2); // ud fifotbl ... |
302 | fifo_push(L, fifo, n); // ud fifo | 305 | fifo_push(L, fifo, n); // ud fifotbl |
303 | lua_settop(L, 0); // | 306 | lua_settop(L, 0); // |
304 | lua_pushboolean(L, 1); // true | 307 | lua_pushboolean(L, 1); // true |
305 | } | 308 | } |
@@ -319,7 +322,7 @@ int keepercall_receive(lua_State* L) | |||
319 | { | 322 | { |
320 | lua_pushvalue(L, i); // fifos keys key[i] | 323 | lua_pushvalue(L, i); // fifos keys key[i] |
321 | lua_rawget(L, 1); // fifos keys fifo | 324 | lua_rawget(L, 1); // fifos keys fifo |
322 | keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // fifos keys fifo | 325 | keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // fifos keys fifotbl |
323 | if (fifo != nullptr && fifo->count > 0) | 326 | if (fifo != nullptr && fifo->count > 0) |
324 | { | 327 | { |
325 | fifo_pop(L, fifo, 1); // fifos keys val | 328 | fifo_pop(L, fifo, 1); // fifos keys val |
@@ -358,7 +361,7 @@ int keepercall_receive_batched(lua_State* L) | |||
358 | lua_pushvalue(L, 1); // key fifos key | 361 | lua_pushvalue(L, 1); // key fifos key |
359 | lua_rawget(L, 2); // key fifos fifo | 362 | lua_rawget(L, 2); // key fifos fifo |
360 | lua_remove(L, 2); // key fifo | 363 | lua_remove(L, 2); // key fifo |
361 | keeper_fifo* const fifo{ prepare_fifo_access(L, 2) }; // key fifo | 364 | keeper_fifo* const fifo{ prepare_fifo_access(L, 2) }; // key fifotbl |
362 | if( fifo != nullptr && fifo->count >= min_count) | 365 | if( fifo != nullptr && fifo->count >= min_count) |
363 | { | 366 | { |
364 | fifo_pop(L, fifo, std::min( max_count, fifo->count)); // key ... | 367 | fifo_pop(L, fifo, std::min( max_count, fifo->count)); // key ... |
@@ -391,8 +394,7 @@ int keepercall_limit(lua_State* L) | |||
391 | if (fifo == nullptr) | 394 | if (fifo == nullptr) |
392 | { // fifos key nil | 395 | { // fifos key nil |
393 | lua_pop(L, 1); // fifos key | 396 | lua_pop(L, 1); // fifos key |
394 | fifo_new(L); // fifos key fifo | 397 | fifo = fifo_new(L); // fifos key fifo |
395 | fifo = keeper_fifo::getPtr(L, -1); | ||
396 | lua_rawset(L, -3); // fifos | 398 | lua_rawset(L, -3); // fifos |
397 | } | 399 | } |
398 | // remove any clutter on the stack | 400 | // remove any clutter on the stack |
@@ -477,10 +479,10 @@ int keepercall_set(lua_State* L) | |||
477 | fifo->first = 1; | 479 | fifo->first = 1; |
478 | fifo->count = 0; | 480 | fifo->count = 0; |
479 | } | 481 | } |
480 | fifo = prepare_fifo_access(L, -1); | 482 | fifo = prepare_fifo_access(L, -1); // fifos key [val [, ...]] fifotbl |
481 | // move the fifo below the values we want to store | 483 | // move the fifo below the values we want to store |
482 | lua_insert(L, 3); // fifos key fifo [val [, ...]] | 484 | lua_insert(L, 3); // fifos key fifotbl [val [, ...]] |
483 | fifo_push(L, fifo, count); // fifos key fifo | 485 | fifo_push(L, fifo, count); // fifos key fifotbl |
484 | } | 486 | } |
485 | return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; | 487 | return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; |
486 | } | 488 | } |
@@ -500,13 +502,13 @@ int keepercall_get(lua_State* L) | |||
500 | push_table(L, 1); // ud key fifos | 502 | push_table(L, 1); // ud key fifos |
501 | lua_replace(L, 1); // fifos key | 503 | lua_replace(L, 1); // fifos key |
502 | lua_rawget(L, 1); // fifos fifo | 504 | lua_rawget(L, 1); // fifos fifo |
503 | keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // fifos fifo | 505 | keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // fifos fifotbl |
504 | if (fifo != nullptr && fifo->count > 0) | 506 | if (fifo != nullptr && fifo->count > 0) |
505 | { | 507 | { |
506 | lua_remove(L, 1); // fifo | 508 | lua_remove(L, 1); // fifotbl |
507 | count = std::min(count, fifo->count); | 509 | count = std::min(count, fifo->count); |
508 | // read <count> value off the fifo | 510 | // read <count> value off the fifo |
509 | fifo_peek(L, fifo, count); // fifo ... | 511 | fifo_peek(L, fifo, count); // fifotbl ... |
510 | return count; | 512 | return count; |
511 | } | 513 | } |
512 | // no fifo was ever registered for this key, or it is empty | 514 | // no fifo was ever registered for this key, or it is empty |
@@ -528,7 +530,7 @@ int keepercall_count(lua_State* L) | |||
528 | lua_pushnil(L); // out fifos nil | 530 | lua_pushnil(L); // out fifos nil |
529 | while (lua_next(L, 2)) // out fifos key fifo | 531 | while (lua_next(L, 2)) // out fifos key fifo |
530 | { | 532 | { |
531 | keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // out fifos key fifo | 533 | keeper_fifo* const fifo{ keeper_fifo::getPtr(L, -1) }; |
532 | lua_pop(L, 1); // out fifos key | 534 | lua_pop(L, 1); // out fifos key |
533 | lua_pushvalue(L, -1); // out fifos key key | 535 | lua_pushvalue(L, -1); // out fifos key key |
534 | lua_pushinteger(L, fifo->count); // out fifos key key count | 536 | lua_pushinteger(L, fifo->count); // out fifos key key count |
@@ -547,7 +549,7 @@ int keepercall_count(lua_State* L) | |||
547 | } | 549 | } |
548 | else // the key is known | 550 | else // the key is known |
549 | { // fifos fifo | 551 | { // fifos fifo |
550 | keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // fifos fifo | 552 | keeper_fifo* const fifo{ keeper_fifo::getPtr(L, -1) }; |
551 | lua_pushinteger(L, fifo->count); // fifos fifo count | 553 | lua_pushinteger(L, fifo->count); // fifos fifo count |
552 | lua_replace(L, -3); // count fifo | 554 | lua_replace(L, -3); // count fifo |
553 | lua_pop(L, 1); // count | 555 | lua_pop(L, 1); // count |
@@ -556,26 +558,26 @@ int keepercall_count(lua_State* L) | |||
556 | 558 | ||
557 | // a variable number of keys is specified: return a table of their counts | 559 | // a variable number of keys is specified: return a table of their counts |
558 | default: // ud keys fifos | 560 | default: // ud keys fifos |
559 | lua_newtable(L); // ud keys fifos out | 561 | lua_newtable(L); // ud keys... fifos out |
560 | lua_replace(L, 1); // out keys fifos | 562 | lua_replace(L, 1); // out keys... fifos |
561 | // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable | 563 | // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable |
562 | lua_insert(L, 2); // out fifos keys | 564 | lua_insert(L, 2); // out fifos keys... |
563 | while (lua_gettop(L) > 2) | 565 | while (lua_gettop(L) > 2) |
564 | { | 566 | { |
565 | lua_pushvalue(L, -1); // out fifos keys key | 567 | lua_pushvalue(L, -1); // out fifos keys... key |
566 | lua_rawget(L, 2); // out fifos keys fifo|nil | 568 | lua_rawget(L, 2); // out fifos keys... fifo|nil |
567 | keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // out fifos keys fifo|nil | 569 | keeper_fifo* const fifo{ keeper_fifo::getPtr(L, -1) }; |
568 | lua_pop(L, 1); // out fifos keys | 570 | lua_pop(L, 1); // out fifos keys... |
569 | if (fifo != nullptr) // the key is known | 571 | if (fifo != nullptr) // the key is known |
570 | { | 572 | { |
571 | lua_pushinteger(L, fifo->count); // out fifos keys count | 573 | lua_pushinteger(L, fifo->count); // out fifos keys... count |
572 | lua_rawset(L, 1); // out fifos keys | 574 | lua_rawset(L, 1); // out fifos keys... |
573 | } | 575 | } |
574 | else // the key is unknown | 576 | else // the key is unknown |
575 | { | 577 | { |
576 | lua_pop(L, 1); // out fifos keys | 578 | lua_pop(L, 1); // out fifos keys... |
577 | } | 579 | } |
578 | } | 580 | } // all keys are exhausted // out fifos |
579 | lua_pop(L, 1); // out | 581 | lua_pop(L, 1); // out |
580 | } | 582 | } |
581 | ASSERT_L(lua_gettop(L) == 1); | 583 | ASSERT_L(lua_gettop(L) == 1); |
diff --git a/src/lanes.cpp b/src/lanes.cpp index df509ee..72652ef 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -572,7 +572,7 @@ static int selfdestruct_gc( lua_State* L) | |||
572 | // no need to mutex-protect this as all threads in the universe are gone at that point | 572 | // no need to mutex-protect this as all threads in the universe are gone at that point |
573 | if( U->timer_deep != nullptr) // test ins case some early internal error prevented Lanes from creating the deep timer | 573 | if( U->timer_deep != nullptr) // test ins case some early internal error prevented Lanes from creating the deep timer |
574 | { | 574 | { |
575 | int const prev_ref_count{ U->timer_deep->m_refcount.fetch_sub(1, std::memory_order_relaxed) }; | 575 | [[maybe_unused]] int const prev_ref_count{ U->timer_deep->m_refcount.fetch_sub(1, std::memory_order_relaxed) }; |
576 | ASSERT_L(prev_ref_count == 1); // this should be the last reference | 576 | ASSERT_L(prev_ref_count == 1); // this should be the last reference |
577 | free_deep_prelude(L, U->timer_deep); | 577 | free_deep_prelude(L, U->timer_deep); |
578 | U->timer_deep = nullptr; | 578 | U->timer_deep = nullptr; |
@@ -1212,7 +1212,7 @@ LUAG_FUNC( lane_new) | |||
1212 | // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) | 1212 | // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) |
1213 | // | 1213 | // |
1214 | // a Lane full userdata needs a single uservalue | 1214 | // a Lane full userdata needs a single uservalue |
1215 | Lane** const ud{ static_cast<Lane**>(lua_newuserdatauv(L, sizeof(Lane*), 1)) }; // func libs priority globals package required gc_cb lane | 1215 | Lane** const ud{ lua_newuserdatauv<Lane*>(L, 1) }; // func libs priority globals package required gc_cb lane |
1216 | Lane* const s{ *ud = static_cast<Lane*>(U->internal_allocator.alloc(sizeof(Lane))) }; // don't forget to store the pointer in the userdata! | 1216 | Lane* const s{ *ud = static_cast<Lane*>(U->internal_allocator.alloc(sizeof(Lane))) }; // don't forget to store the pointer in the userdata! |
1217 | if( s == nullptr) | 1217 | if( s == nullptr) |
1218 | { | 1218 | { |
@@ -1915,8 +1915,7 @@ LUAG_FUNC( configure) | |||
1915 | STACK_CHECK( L, 2); | 1915 | STACK_CHECK( L, 2); |
1916 | 1916 | ||
1917 | { | 1917 | { |
1918 | char const* errmsg; | 1918 | char const* errmsg{ push_deep_proxy(L, U->timer_deep, 0, eLM_LaneBody) }; // settings M timer_deep |
1919 | errmsg = push_deep_proxy(L, U->timer_deep, 0, eLM_LaneBody); // settings M timer_deep | ||
1920 | if( errmsg != nullptr) | 1919 | if( errmsg != nullptr) |
1921 | { | 1920 | { |
1922 | return luaL_error( L, errmsg); | 1921 | return luaL_error( L, errmsg); |
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 23fa0e9..63bc8d1 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
@@ -147,3 +147,9 @@ auto lua_tolightuserdata(lua_State* L, int index_) | |||
147 | return static_cast<T*>(lua_touserdata(L, index_)); | 147 | return static_cast<T*>(lua_touserdata(L, index_)); |
148 | } | 148 | } |
149 | } | 149 | } |
150 | |||
151 | template <typename T> | ||
152 | T* lua_newuserdatauv(lua_State* L, int nuvalue_) | ||
153 | { | ||
154 | return static_cast<T*>(lua_newuserdatauv(L, sizeof(T), nuvalue_)); | ||
155 | } | ||