From bfb1277b3496018b7ee12eca2fb900ebbe651b49 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Fri, 22 Mar 2024 15:36:45 +0100 Subject: C++ migration: STACK_GROW is no longer a macro, sanitized and fixed warnings in keeper.cpp --- src/compat.cpp | 5 +- src/keeper.cpp | 756 +++++++++++++++++++++++++------------------------ src/keeper.h | 42 +-- src/lanes.cpp | 2 +- src/macros_and_utils.h | 7 +- src/platform.h | 1 + 6 files changed, 419 insertions(+), 394 deletions(-) (limited to 'src') diff --git a/src/compat.cpp b/src/compat.cpp index 19159a9..47fe37e 100644 --- a/src/compat.cpp +++ b/src/compat.cpp @@ -51,8 +51,10 @@ void* lua_newuserdatauv( lua_State* L, size_t sz, int nuvalue) return lua_newuserdata( L, sz); } -int lua_getiuservalue( lua_State* L, int idx, int n) +// push on stack uservalue #n of full userdata at idx +int lua_getiuservalue(lua_State* L, int idx, int n) { + // full userdata can have only 1 uservalue before 5.4 if( n > 1) { lua_pushnil( L); @@ -76,6 +78,7 @@ int lua_getiuservalue( lua_State* L, int idx, int n) return lua_type( L, -1); } +// pop stack top, sets it a uservalue #n of full userdata at idx int lua_setiuservalue( lua_State* L, int idx, int n) { if( n > 1 diff --git a/src/keeper.cpp b/src/keeper.cpp index c886718..0cb1a94 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp @@ -1,6 +1,6 @@ /* -- - -- KEEPER.C + -- KEEPER.CPP -- -- Keeper state logic -- @@ -14,7 +14,7 @@ --[[ =============================================================================== - Copyright (C) 2011-2013 Benoit Germain + Copyright (C) 2011-2023 Benoit Germain Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -37,319 +37,324 @@ =============================================================================== ]]-- */ - -#include -#include -#include -#include -#include - #include "keeper.h" + #include "compat.h" -#include "tools.h" #include "state.h" -#include "universe.h" +#include "tools.h" #include "uniquekey.h" +#include "universe.h" -//################################################################################### -// Keeper implementation -//################################################################################### +#include +#include -#ifndef __min -#define __min( a, b) (((a) < (b)) ? (a) : (b)) -#endif // __min +// ################################################################################### +// Keeper implementation +// ################################################################################### struct keeper_fifo { - lua_Integer first; - lua_Integer count; - lua_Integer limit; + int first{ 1 }; + int count{ 0 }; + int limit{ -1 }; }; -static int const CONTENTS_TABLE = 1; +static constexpr int CONTENTS_TABLE{ 1 }; + +// ################################################################################################## // replaces the fifo ud by its uservalue on the stack -static keeper_fifo* prepare_fifo_access( lua_State* L, int idx_) +static keeper_fifo* prepare_fifo_access(lua_State* L, int idx_) { - keeper_fifo* fifo = (keeper_fifo*) lua_touserdata( L, idx_); - if( fifo != nullptr) + keeper_fifo* const fifo{ static_cast(lua_touserdata(L, idx_)) }; + if (fifo != nullptr) { - idx_ = lua_absindex( L, idx_); - STACK_GROW( L, 1); + idx_ = lua_absindex(L, idx_); + STACK_GROW(L, 1); // we can replace the fifo userdata in the stack without fear of it being GCed, there are other references around - lua_getiuservalue( L, idx_, CONTENTS_TABLE); - lua_replace( L, idx_); + lua_getiuservalue(L, idx_, CONTENTS_TABLE); + lua_replace(L, idx_); } return fifo; } +// ################################################################################################## + // in: nothing // out: { first = 1, count = 0, limit = -1} -static void fifo_new( lua_State* L) +static void fifo_new(lua_State* L) { keeper_fifo* fifo; - STACK_GROW( L, 2); + STACK_GROW(L, 2); // a fifo full userdata has one uservalue, the table that holds the actual fifo contents - fifo = (keeper_fifo*)lua_newuserdatauv( L, sizeof( keeper_fifo), 1); - fifo->first = 1; - fifo->count = 0; - fifo->limit = -1; - lua_newtable( L); - lua_setiuservalue( L, -2, CONTENTS_TABLE); + fifo = (keeper_fifo*) lua_newuserdatauv(L, sizeof(keeper_fifo), 1); + fifo->keeper_fifo::keeper_fifo(); + lua_newtable(L); + lua_setiuservalue(L, -2, CONTENTS_TABLE); } +// ################################################################################################## + // in: expect fifo ... on top of the stack // out: nothing, removes all pushed values from the stack -static void fifo_push( lua_State* L, keeper_fifo* fifo_, lua_Integer count_) +static void fifo_push(lua_State* L, keeper_fifo* fifo_, int count_) { - int const idx = lua_gettop( L) - (int) count_; - lua_Integer start = fifo_->first + fifo_->count - 1; - lua_Integer i; + int const idx{ lua_gettop(L) - count_ }; + int const start{ fifo_->first + fifo_->count - 1 }; // pop all additional arguments, storing them in the fifo - for( i = count_; i >= 1; -- i) + for (int i = count_; i >= 1; --i) { // store in the fifo the value at the top of the stack at the specified index, popping it from the stack - lua_rawseti( L, idx, (int)(start + i)); + lua_rawseti(L, idx, start + i); } fifo_->count += count_; } +// ################################################################################################## + // in: fifo // out: ...|nothing // expects exactly 1 value on the stack! // currently only called with a count of 1, but this may change in the future // function assumes that there is enough data in the fifo to satisfy the request -static void fifo_peek( lua_State* L, keeper_fifo* fifo_, lua_Integer count_) +static void fifo_peek(lua_State* L, keeper_fifo* fifo_, int count_) { - lua_Integer i; - STACK_GROW( L, count_); - for( i = 0; i < count_; ++ i) + STACK_GROW(L, count_); + for (int i = 0; i < count_; ++i) { - lua_rawgeti( L, 1, (int)( fifo_->first + i)); + lua_rawgeti(L, 1, (fifo_->first + i)); } } +// ################################################################################################## + // in: fifo // out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) -static void fifo_pop( lua_State* L, keeper_fifo* fifo_, lua_Integer count_) +static void fifo_pop( lua_State* L, keeper_fifo* fifo_, int count_) { - int const fifo_idx = lua_gettop( L); // ... fifo - int i; + int const fifo_idx = lua_gettop(L); // ... fifo // each iteration pushes a value on the stack! - STACK_GROW( L, count_ + 2); + STACK_GROW(L, count_ + 2); // skip first item, we will push it last - for( i = 1; i < count_; ++ i) + for (int i = 1; i < count_; ++i) { - int const at = (int)( fifo_->first + i); + int const at{ fifo_->first + i }; // push item on the stack - lua_rawgeti( L, fifo_idx, at); // ... fifo val + lua_rawgeti(L, fifo_idx, at); // ... fifo val // remove item from the fifo - lua_pushnil( L); // ... fifo val nil - lua_rawseti( L, fifo_idx, at); // ... fifo val + lua_pushnil(L); // ... fifo val nil + lua_rawseti(L, fifo_idx, at); // ... fifo val } // now process first item { - int const at = (int)( fifo_->first); - lua_rawgeti( L, fifo_idx, at); // ... fifo vals val - lua_pushnil( L); // ... fifo vals val nil - lua_rawseti( L, fifo_idx, at); // ... fifo vals val - lua_replace( L, fifo_idx); // ... vals + int const at{ fifo_->first }; + lua_rawgeti(L, fifo_idx, at); // ... fifo vals val + lua_pushnil(L); // ... fifo vals val nil + lua_rawseti(L, fifo_idx, at); // ... fifo vals val + lua_replace(L, fifo_idx); // ... vals } { // avoid ever-growing indexes by resetting each time we detect the fifo is empty - lua_Integer const new_count = fifo_->count - count_; + int const new_count{ fifo_->count - count_ }; fifo_->first = (new_count == 0) ? 1 : (fifo_->first + count_); fifo_->count = new_count; } } +// ################################################################################################## + // in: linda_ud expected at *absolute* stack slot idx // out: fifos[ud] // crc64/we of string "FIFOS_KEY" generated at http://www.nitrxgen.net/hashgen/ static constexpr UniqueKey FIFOS_KEY{ 0xdce50bbc351cd465ull }; -static void push_table( lua_State* L, int idx_) +static void push_table(lua_State* L, int idx_) { - STACK_GROW( L, 4); - STACK_CHECK( L, 0); - idx_ = lua_absindex( L, idx_); - FIFOS_KEY.query_registry(L); // ud fifos - lua_pushvalue( L, idx_); // ud fifos ud - lua_rawget( L, -2); // ud fifos fifos[ud] - STACK_MID( L, 2); - if( lua_isnil( L, -1)) + STACK_GROW(L, 4); + STACK_CHECK(L, 0); + idx_ = lua_absindex(L, idx_); + FIFOS_KEY.query_registry(L); // ud fifos + lua_pushvalue(L, idx_); // ud fifos ud + lua_rawget(L, -2); // ud fifos fifos[ud] + STACK_MID(L, 2); + if (lua_isnil(L, -1)) { - lua_pop( L, 1); // ud fifos + lua_pop(L, 1); // ud fifos // add a new fifos table for this linda - lua_newtable( L); // ud fifos fifos[ud] - lua_pushvalue( L, idx_); // ud fifos fifos[ud] ud - lua_pushvalue( L, -2); // ud fifos fifos[ud] ud fifos[ud] - lua_rawset( L, -4); // ud fifos fifos[ud] + lua_newtable(L); // ud fifos fifos[ud] + lua_pushvalue(L, idx_); // ud fifos fifos[ud] ud + lua_pushvalue(L, -2); // ud fifos fifos[ud] ud fifos[ud] + lua_rawset(L, -4); // ud fifos fifos[ud] } - lua_remove( L, -2); // ud fifos[ud] - STACK_END( L, 1); + lua_remove(L, -2); // ud fifos[ud] + STACK_END(L, 1); } -int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_) +// ################################################################################################## + +int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_) { Keeper* const K = which_keeper( U->keepers, magic_); lua_State* const KL = K ? K->L : nullptr; if( KL == nullptr) return 0; - STACK_GROW( KL, 4); - STACK_CHECK( KL, 0); - FIFOS_KEY.query_registry(KL); // fifos - lua_pushlightuserdata( KL, ptr_); // fifos ud - lua_rawget( KL, -2); // fifos storage - lua_remove( KL, -2); // storage - if( !lua_istable( KL, -1)) + STACK_GROW(KL, 4); + STACK_CHECK(KL, 0); + FIFOS_KEY.query_registry(KL); // fifos + lua_pushlightuserdata(KL, ptr_); // fifos ud + lua_rawget(KL, -2); // fifos storage + lua_remove(KL, -2); // storage + if( !lua_istable(KL, -1)) { - lua_pop( KL, 1); // - STACK_MID( KL, 0); + lua_pop(KL, 1); // + STACK_MID(KL, 0); return 0; } - // move data from keeper to destination state KEEPER MAIN - lua_pushnil( KL); // storage nil - STACK_GROW( L, 5); - STACK_CHECK( L, 0); - lua_newtable( L); // out - while( lua_next( KL, -2)) // storage key fifo + // move data from keeper to destination state KEEPER MAIN + lua_pushnil(KL); // storage nil + STACK_GROW(L, 5); + STACK_CHECK(L, 0); + lua_newtable(L); // out + while( lua_next(KL, -2)) // storage key fifo { - keeper_fifo* fifo = prepare_fifo_access( KL, -1); // storage key fifo - lua_pushvalue( KL, -2); // storage key fifo key - luaG_inter_move( U, KL, L, 1, eLM_FromKeeper); // storage key fifo // out key - STACK_MID( L, 2); - lua_newtable( L); // out key keyout - luaG_inter_move( U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo - lua_pushinteger( L, fifo->first); // out key keyout fifo first - STACK_MID( L, 5); - lua_setfield( L, -3, "first"); // out key keyout fifo - lua_pushinteger( L, fifo->count); // out key keyout fifo count - STACK_MID( L, 5); - lua_setfield( L, -3, "count"); // out key keyout fifo - lua_pushinteger( L, fifo->limit); // out key keyout fifo limit - STACK_MID( L, 5); - lua_setfield( L, -3, "limit"); // out key keyout fifo - lua_setfield( L, -2, "fifo"); // out key keyout - lua_rawset( L, -3); // out - STACK_MID( L, 1); + keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifo + lua_pushvalue(KL, -2); // storage key fifo key + luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key fifo // out key + STACK_MID(L, 2); + lua_newtable(L); // out key keyout + luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo + lua_pushinteger(L, fifo->first); // out key keyout fifo first + STACK_MID(L, 5); + lua_setfield(L, -3, "first"); // out key keyout fifo + lua_pushinteger(L, fifo->count); // out key keyout fifo count + STACK_MID(L, 5); + lua_setfield(L, -3, "count"); // out key keyout fifo + lua_pushinteger(L, fifo->limit); // out key keyout fifo limit + STACK_MID(L, 5); + lua_setfield(L, -3, "limit"); // out key keyout fifo + lua_setfield(L, -2, "fifo"); // out key keyout + lua_rawset(L, -3); // out + STACK_MID(L, 1); } - STACK_END( L, 1); - lua_pop( KL, 1); // - STACK_END( KL, 0); + STACK_END(L, 1); + lua_pop(KL, 1); // + STACK_END(KL, 0); return 1; } +// ################################################################################################## + // in: linda_ud -int keepercall_clear( lua_State* L) +int keepercall_clear(lua_State* L) { - STACK_GROW( L, 3); - STACK_CHECK( L, 0); - FIFOS_KEY.query_registry(L); // ud fifos - lua_pushvalue( L, 1); // ud fifos ud - lua_pushnil( L); // ud fifos ud nil - lua_rawset( L, -3); // ud fifos - lua_pop( L, 1); // ud - STACK_END( L, 0); + STACK_GROW(L, 3); + STACK_CHECK(L, 0); + FIFOS_KEY.query_registry(L); // ud fifos + lua_pushvalue(L, 1); // ud fifos ud + lua_pushnil(L); // ud fifos ud nil + lua_rawset(L, -3); // ud fifos + lua_pop(L, 1); // ud + STACK_END(L, 0); return 0; } +// ################################################################################################## // in: linda_ud, key, ... // out: true|false -int keepercall_send( lua_State* L) +int keepercall_send(lua_State* L) { - keeper_fifo* fifo; - int n = lua_gettop( L) - 2; - push_table( L, 1); // ud key ... fifos + int const n{ lua_gettop(L) - 2 }; + push_table(L, 1); // ud key ... fifos // get the fifo associated to this key in this linda, create it if it doesn't exist - lua_pushvalue( L, 2); // ud key ... fifos key - lua_rawget( L, -2); // ud key ... fifos fifo - if( lua_isnil( L, -1)) + lua_pushvalue(L, 2); // ud key ... fifos key + lua_rawget(L, -2); // ud key ... fifos fifo + if( lua_isnil(L, -1)) { - lua_pop( L, 1); // ud key ... fifos - fifo_new( L); // ud key ... fifos fifo - lua_pushvalue( L, 2); // ud key ... fifos fifo key - lua_pushvalue( L, -2); // ud key ... fifos fifo key fifo - lua_rawset( L, -4); // ud key ... fifos fifo + lua_pop(L, 1); // ud key ... fifos + fifo_new(L); // ud key ... fifos fifo + lua_pushvalue(L, 2); // ud key ... fifos fifo key + lua_pushvalue(L, -2); // ud key ... fifos fifo key fifo + lua_rawset(L, -4); // ud key ... fifos fifo } - lua_remove( L, -2); // ud key ... fifo - fifo = (keeper_fifo*) lua_touserdata( L, -1); + lua_remove(L, -2); // ud key ... fifo + keeper_fifo* fifo{ static_cast(lua_touserdata(L, -1)) }; if( fifo->limit >= 0 && fifo->count + n > fifo->limit) { - lua_settop( L, 0); // - lua_pushboolean( L, 0); // false + lua_settop(L, 0); // + lua_pushboolean(L, 0); // false } else { - fifo = prepare_fifo_access( L, -1); - lua_replace( L, 2); // ud fifo ... - fifo_push( L, fifo, n); // ud fifo - lua_settop( L, 0); // - lua_pushboolean( L, 1); // true + fifo = prepare_fifo_access(L, -1); + lua_replace(L, 2); // ud fifo ... + fifo_push(L, fifo, n); // ud fifo + lua_settop(L, 0); // + lua_pushboolean(L, 1); // true } return 1; } +// ################################################################################################## + // in: linda_ud, key [, key]? // out: (key, val) or nothing -int keepercall_receive( lua_State* L) +int keepercall_receive(lua_State* L) { - int top = lua_gettop( L); - int i; - push_table( L, 1); // ud keys fifos - lua_replace( L, 1); // fifos keys - for( i = 2; i <= top; ++ i) + int const top{ lua_gettop(L) }; + push_table(L, 1); // ud keys fifos + lua_replace(L, 1); // fifos keys + for (int i = 2; i <= top; ++i) { - keeper_fifo* fifo; - lua_pushvalue( L, i); // fifos keys key[i] - lua_rawget( L, 1); // fifos keys fifo - fifo = prepare_fifo_access( L, -1); // fifos keys fifo - if( fifo != nullptr && fifo->count > 0) + lua_pushvalue(L, i); // fifos keys key[i] + lua_rawget(L, 1); // fifos keys fifo + keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // fifos keys fifo + if (fifo != nullptr && fifo->count > 0) { - fifo_pop( L, fifo, 1); // fifos keys val - if( !lua_isnil( L, -1)) + fifo_pop(L, fifo, 1); // fifos keys val + if (!lua_isnil(L, -1)) { - lua_replace( L, 1); // val keys - lua_settop( L, i); // val keys key[i] - if( i != 2) + lua_replace(L, 1); // val keys + lua_settop(L, i); // val keys key[i] + if (i != 2) { - lua_replace( L, 2); // val key keys - lua_settop( L, 2); // val key + lua_replace(L, 2); // val key keys + lua_settop(L, 2); // val key } - lua_insert( L, 1); // key, val + lua_insert(L, 1); // key, val return 2; } } - lua_settop( L, top); // data keys + lua_settop(L, top); // data keys } // nothing to receive return 0; } -//in: linda_ud key mincount [maxcount] -int keepercall_receive_batched( lua_State* L) +// ################################################################################################## + +// in: linda_ud key mincount [maxcount] +int keepercall_receive_batched(lua_State* L) { - lua_Integer const min_count = lua_tointeger( L, 3); + int const min_count{ static_cast(lua_tointeger(L, 3)) }; if( min_count > 0) { - keeper_fifo* fifo; - lua_Integer const max_count = luaL_optinteger( L, 4, min_count); - lua_settop( L, 2); // ud key - lua_insert( L, 1); // key ud - push_table( L, 2); // key ud fifos - lua_remove( L, 2); // key fifos - lua_pushvalue( L, 1); // key fifos key - lua_rawget( L, 2); // key fifos fifo - lua_remove( L, 2); // key fifo - fifo = prepare_fifo_access( L, 2); // key fifo + int const max_count{ static_cast(luaL_optinteger(L, 4, min_count)) }; + lua_settop(L, 2); // ud key + lua_insert(L, 1); // key ud + push_table(L, 2); // key ud fifos + lua_remove(L, 2); // key fifos + lua_pushvalue(L, 1); // key fifos key + lua_rawget(L, 2); // key fifos fifo + lua_remove(L, 2); // key fifo + keeper_fifo* const fifo{ prepare_fifo_access(L, 2) }; // key fifo if( fifo != nullptr && fifo->count >= min_count) { - fifo_pop( L, fifo, __min( max_count, fifo->count)); // key ... + fifo_pop(L, fifo, std::min( max_count, fifo->count)); // key ... } else { - lua_settop( L, 0); + lua_settop(L, 0); // } - return lua_gettop( L); + return lua_gettop(L); } else { @@ -357,35 +362,36 @@ int keepercall_receive_batched( lua_State* L) } } +// ################################################################################################## + // in: linda_ud key n // out: true or nil -int keepercall_limit( lua_State* L) +int keepercall_limit(lua_State* L) { - keeper_fifo* fifo; - lua_Integer limit = lua_tointeger( L, 3); - push_table( L, 1); // ud key n fifos - lua_replace( L, 1); // fifos key n - lua_pop( L, 1); // fifos key - lua_pushvalue( L, -1); // fifos key key - lua_rawget( L, -3); // fifos key fifo|nil - fifo = (keeper_fifo*) lua_touserdata( L, -1); - if( fifo == nullptr) - { // fifos key nil - lua_pop( L, 1); // fifos key - fifo_new( L); // fifos key fifo - fifo = (keeper_fifo*) lua_touserdata( L, -1); - lua_rawset( L, -3); // fifos + int const limit{ static_cast(lua_tointeger(L, 3)) }; + push_table(L, 1); // ud key n fifos + lua_replace(L, 1); // fifos key n + lua_pop(L, 1); // fifos key + lua_pushvalue(L, -1); // fifos key key + lua_rawget(L, -3); // fifos key fifo|nil + keeper_fifo* fifo{ static_cast(lua_touserdata(L, -1)) }; + if (fifo == nullptr) + { // fifos key nil + lua_pop(L, 1); // fifos key + fifo_new(L); // fifos key fifo + fifo = static_cast(lua_touserdata(L, -1)); + lua_rawset(L, -3); // fifos } // remove any clutter on the stack - lua_settop( L, 0); + lua_settop(L, 0); // return true if we decide that blocked threads waiting to write on that key should be awakened // this is the case if we detect the key was full but it is no longer the case if( - ((fifo->limit >= 0) && (fifo->count >= fifo->limit)) // the key was full if limited and count exceeded the previous limit - && ((limit < 0) || (fifo->count < limit)) // the key is not full if unlimited or count is lower than the new limit + ((fifo->limit >= 0) && (fifo->count >= fifo->limit)) // the key was full if limited and count exceeded the previous limit + && ((limit < 0) || (fifo->count < limit)) // the key is not full if unlimited or count is lower than the new limit ) { - lua_pushboolean( L, 1); + lua_pushboolean(L, 1); // true } // set the new limit fifo->limit = limit; @@ -393,40 +399,41 @@ int keepercall_limit( lua_State* L) return lua_gettop( L); } -//in: linda_ud key [[val] ...] +// ################################################################################################## + +// in: linda_ud key [[val] ...] //out: true or nil -int keepercall_set( lua_State* L) +int keepercall_set(lua_State* L) { bool should_wake_writers{ false }; - STACK_GROW( L, 6); + STACK_GROW(L, 6); // retrieve fifos associated with the linda - push_table( L, 1); // ud key [val [, ...]] fifos - lua_replace( L, 1); // fifos key [val [, ...]] + push_table(L, 1); // ud key [val [, ...]] fifos + lua_replace(L, 1); // fifos key [val [, ...]] // make sure we have a value on the stack - if( lua_gettop( L) == 2) // fifos key + if (lua_gettop(L) == 2) // fifos key { - keeper_fifo* fifo; - lua_pushvalue( L, -1); // fifos key key - lua_rawget( L, 1); // fifos key fifo|nil + lua_pushvalue(L, -1); // fifos key key + lua_rawget(L, 1); // fifos key fifo|nil // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! - fifo = (keeper_fifo*) lua_touserdata( L, -1); - if( fifo != nullptr) // might be nullptr if we set a nonexistent key to nil - { // fifos key fifo - if( fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it + keeper_fifo* const fifo{ static_cast(lua_touserdata(L, -1)) }; + if (fifo != nullptr) // might be nullptr if we set a nonexistent key to nil + { // fifos key fifo + if (fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it { - lua_pop( L, 1); // fifos key - lua_pushnil( L); // fifos key nil - lua_rawset( L, -3); // fifos + lua_pop(L, 1); // fifos key + lua_pushnil(L); // fifos key nil + lua_rawset(L, -3); // fifos } else { // we create room if the fifo was full but it is no longer the case should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit); - lua_remove( L, -2); // fifos fifo - lua_newtable( L); // fifos fifo {} - lua_setiuservalue( L, -2, CONTENTS_TABLE); // fifos fifo + lua_remove(L, -2); // fifos fifo + lua_newtable(L); // fifos fifo {} + lua_setiuservalue(L, -2, CONTENTS_TABLE); // fifos fifo fifo->first = 1; fifo->count = 0; } @@ -434,133 +441,131 @@ int keepercall_set( lua_State* L) } else // set/replace contents stored at the specified key? { - lua_Integer count = lua_gettop( L) - 2; // number of items we want to store - keeper_fifo* fifo; // fifos key [val [, ...]] - lua_pushvalue( L, 2); // fifos key [val [, ...]] key - lua_rawget( L, 1); // fifos key [val [, ...]] fifo|nil - fifo = (keeper_fifo*) lua_touserdata( L, -1); + int const count{ lua_gettop(L) - 2 }; // number of items we want to store + lua_pushvalue(L, 2); // fifos key [val [, ...]] key + lua_rawget(L, 1); // fifos key [val [, ...]] fifo|nil + keeper_fifo* fifo = static_cast(lua_touserdata( L, -1)); if( fifo == nullptr) // can be nullptr if we store a value at a new key - { // fifos key [val [, ...]] nil + { // fifos key [val [, ...]] nil // no need to wake writers in that case, because a writer can't wait on an inexistent key - lua_pop( L, 1); // fifos key [val [, ...]] - fifo_new( L); // fifos key [val [, ...]] fifo - lua_pushvalue( L, 2); // fifos key [val [, ...]] fifo key - lua_pushvalue( L, -2); // fifos key [val [, ...]] fifo key fifo - lua_rawset( L, 1); // fifos key [val [, ...]] fifo + lua_pop(L, 1); // fifos key [val [, ...]] + fifo_new(L); // fifos key [val [, ...]] fifo + lua_pushvalue(L, 2); // fifos key [val [, ...]] fifo key + lua_pushvalue(L, -2); // fifos key [val [, ...]] fifo key fifo + lua_rawset(L, 1); // fifos key [val [, ...]] fifo } else // the fifo exists, we just want to update its contents - { // fifos key [val [, ...]] fifo + { // fifos key [val [, ...]] fifo // we create room if the fifo was full but it is no longer the case should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit); // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! - lua_newtable( L); // fifos key [val [, ...]] fifo {} - lua_setiuservalue( L, -2, CONTENTS_TABLE); // fifos key [val [, ...]] fifo + lua_newtable(L); // fifos key [val [, ...]] fifo {} + lua_setiuservalue(L, -2, CONTENTS_TABLE); // fifos key [val [, ...]] fifo fifo->first = 1; fifo->count = 0; } - fifo = prepare_fifo_access( L, -1); + fifo = prepare_fifo_access(L, -1); // move the fifo below the values we want to store - lua_insert( L, 3); // fifos key fifo [val [, ...]] - fifo_push( L, fifo, count); // fifos key fifo + lua_insert(L, 3); // fifos key fifo [val [, ...]] + fifo_push(L, fifo, count); // fifos key fifo } return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; } +// ################################################################################################## + // in: linda_ud key [count] // out: at most values -int keepercall_get( lua_State* L) +int keepercall_get(lua_State* L) { - keeper_fifo* fifo; - lua_Integer count = 1; - if( lua_gettop( L) == 3) // ud key count + int count{ 1 }; + if (lua_gettop(L) == 3) // ud key count { - count = lua_tointeger( L, 3); - lua_pop( L, 1); // ud key + count = static_cast(lua_tointeger(L, 3)); + lua_pop(L, 1); // ud key } - push_table( L, 1); // ud key fifos - lua_replace( L, 1); // fifos key - lua_rawget( L, 1); // fifos fifo - fifo = prepare_fifo_access( L, -1); // fifos fifo - if( fifo != nullptr && fifo->count > 0) + push_table(L, 1); // ud key fifos + lua_replace(L, 1); // fifos key + lua_rawget(L, 1); // fifos fifo + keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // fifos fifo + if (fifo != nullptr && fifo->count > 0) { - lua_remove( L, 1); // fifo - count = __min( count, fifo->count); + lua_remove(L, 1); // fifo + count = std::min(count, fifo->count); // read value off the fifo - fifo_peek( L, fifo, count); // fifo ... - return (int) count; + fifo_peek(L, fifo, count); // fifo ... + return count; } // no fifo was ever registered for this key, or it is empty return 0; } +// ################################################################################################## + // in: linda_ud [, key [, ...]] -int keepercall_count( lua_State* L) +int keepercall_count(lua_State* L) { - push_table( L, 1); // ud keys fifos - switch( lua_gettop( L)) + push_table(L, 1); // ud keys fifos + switch (lua_gettop(L)) { // no key is specified: return a table giving the count of all known keys - case 2: // ud fifos - lua_newtable( L); // ud fifos out - lua_replace( L, 1); // out fifos - lua_pushnil( L); // out fifos nil - while( lua_next( L, 2)) // out fifos key fifo + case 2: // ud fifos + lua_newtable(L); // ud fifos out + lua_replace(L, 1); // out fifos + lua_pushnil(L); // out fifos nil + while (lua_next(L, 2)) // out fifos key fifo { - keeper_fifo* fifo = prepare_fifo_access( L, -1); // out fifos key fifo - lua_pop( L, 1); // out fifos key - lua_pushvalue( L, -1); // out fifos key key - lua_pushinteger( L, fifo->count); // out fifos key key count - lua_rawset( L, -5); // out fifos key + keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // out fifos key fifo + lua_pop(L, 1); // out fifos key + lua_pushvalue(L, -1); // out fifos key key + lua_pushinteger(L, fifo->count); // out fifos key key count + lua_rawset(L, -5); // out fifos key } - lua_pop( L, 1); // out + lua_pop(L, 1); // out break; // 1 key is specified: return its count - case 3: // ud key fifos - { - keeper_fifo* fifo; - lua_replace( L, 1); // fifos key - lua_rawget( L, -2); // fifos fifo|nil - if( lua_isnil( L, -1)) // the key is unknown - { // fifos nil - lua_remove( L, -2); // nil - } - else // the key is known - { // fifos fifo - fifo = prepare_fifo_access( L, -1); // fifos fifo - lua_pushinteger( L, fifo->count); // fifos fifo count - lua_replace( L, -3); // count fifo - lua_pop( L, 1); // count - } + case 3: // ud key fifos + lua_replace(L, 1); // fifos key + lua_rawget(L, -2); // fifos fifo|nil + if (lua_isnil(L, -1)) // the key is unknown + { // fifos nil + lua_remove(L, -2); // nil + } + else // the key is known + { // fifos fifo + keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // fifos fifo + lua_pushinteger(L, fifo->count); // fifos fifo count + lua_replace(L, -3); // count fifo + lua_pop(L, 1); // count } break; // a variable number of keys is specified: return a table of their counts - default: // ud keys fifos - lua_newtable( L); // ud keys fifos out - lua_replace( L, 1); // out keys fifos + default: // ud keys fifos + lua_newtable(L); // ud keys fifos out + lua_replace(L, 1); // out keys fifos // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable - lua_insert( L, 2); // out fifos keys - while( lua_gettop( L) > 2) + lua_insert(L, 2); // out fifos keys + while (lua_gettop(L) > 2) { - keeper_fifo* fifo; - lua_pushvalue( L, -1); // out fifos keys key - lua_rawget( L, 2); // out fifos keys fifo|nil - fifo = prepare_fifo_access( L, -1); // out fifos keys fifo|nil - lua_pop( L, 1); // out fifos keys - if( fifo != nullptr) // the key is known + lua_pushvalue(L, -1); // out fifos keys key + lua_rawget(L, 2); // out fifos keys fifo|nil + keeper_fifo* const fifo{ prepare_fifo_access(L, -1) }; // out fifos keys fifo|nil + lua_pop(L, 1); // out fifos keys + if (fifo != nullptr) // the key is known { - lua_pushinteger( L, fifo->count); // out fifos keys count - lua_rawset( L, 1); // out fifos keys + lua_pushinteger(L, fifo->count); // out fifos keys count + lua_rawset(L, 1); // out fifos keys } else // the key is unknown { - lua_pop( L, 1); // out fifos keys + lua_pop(L, 1); // out fifos keys } } - lua_pop( L, 1); // out + lua_pop(L, 1); // out } - ASSERT_L( lua_gettop( L) == 1); + ASSERT_L(lua_gettop(L) == 1); return 1; } @@ -580,24 +585,23 @@ int keepercall_count( lua_State* L) */ // called as __gc for the keepers array userdata -void close_keepers( Universe* U) +void close_keepers(Universe* U) { - if( U->keepers != nullptr) + if (U->keepers != nullptr) { - int i; int nbKeepers = U->keepers->nb_keepers; // NOTE: imagine some keeper state N+1 currently holds a linda that uses another keeper N, and a _gc that will make use of it // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success // which is early-outed with a U->keepers->nbKeepers null-check U->keepers->nb_keepers = 0; - for( i = 0; i < nbKeepers; ++ i) + for (int i = 0; i < nbKeepers; ++i) { lua_State* K = U->keepers->keeper_array[i].L; U->keepers->keeper_array[i].L = nullptr; - if( K != nullptr) + if (K != nullptr) { - lua_close( K); + lua_close(K); } else { @@ -605,19 +609,21 @@ void close_keepers( Universe* U) nbKeepers = i; } } - for( i = 0; i < nbKeepers; ++ i) + for (int i = 0; i < nbKeepers; ++i) { - MUTEX_FREE( &U->keepers->keeper_array[i].keeper_cs); + MUTEX_FREE(&U->keepers->keeper_array[i].keeper_cs); } // free the keeper bookkeeping structure { AllocatorDefinition* const allocD = &U->internal_allocator; - (void) allocD->allocF( allocD->allocUD, U->keepers, sizeof( Keepers) + (nbKeepers - 1) * sizeof( Keeper), 0); + std::ignore = allocD->allocF(allocD->allocUD, U->keepers, sizeof(Keepers) + (nbKeepers - 1) * sizeof(Keeper), 0); U->keepers = nullptr; } } } +// ################################################################################################## + /* * Initialize keeper states * @@ -629,42 +635,39 @@ void close_keepers( Universe* U) * function never fails. * settings table is at position 1 on the stack */ -void init_keepers( Universe* U, lua_State* L) +void init_keepers(Universe* U, lua_State* L) { - int i; - int nb_keepers; - - STACK_CHECK( L, 0); // L K - lua_getfield( L, 1, "nb_keepers"); // nb_keepers - nb_keepers = (int) lua_tointeger( L, -1); - lua_pop( L, 1); // - if( nb_keepers < 1) + STACK_CHECK(L, 0); // L K + lua_getfield(L, 1, "nb_keepers"); // nb_keepers + int nb_keepers{ static_cast(lua_tointeger(L, -1)) }; + lua_pop(L, 1); // + if (nb_keepers < 1) { - (void) luaL_error( L, "Bad number of keepers (%d)", nb_keepers); + (void) luaL_error(L, "Bad number of keepers (%d)", nb_keepers); } // Keepers contains an array of 1 Keeper, adjust for the actual number of keeper states { - size_t const bytes = sizeof( Keepers) + (nb_keepers - 1) * sizeof( Keeper); + size_t const bytes = sizeof(Keepers) + (nb_keepers - 1) * sizeof(Keeper); { AllocatorDefinition* const allocD = &U->internal_allocator; - U->keepers = (Keepers*) allocD->allocF( allocD->allocUD, nullptr, 0, bytes); + U->keepers = (Keepers*) allocD->allocF(allocD->allocUD, nullptr, 0, bytes); } - if( U->keepers == nullptr) + if (U->keepers == nullptr) { - (void) luaL_error( L, "init_keepers() failed while creating keeper array; out of memory"); + (void) luaL_error(L, "init_keepers() failed while creating keeper array; out of memory"); return; } - memset( U->keepers, 0, bytes); + memset(U->keepers, 0, bytes); U->keepers->nb_keepers = nb_keepers; } - for( i = 0; i < nb_keepers; ++ i) // keepersUD + for (int i = 0; i < nb_keepers; ++i) // keepersUD { // note that we will leak K if we raise an error later - lua_State* K = create_state( U, L); - if( K == nullptr) + lua_State* const K{ create_state(U, L) }; + if (K == nullptr) { - (void) luaL_error( L, "init_keepers() failed while creating keeper states; out of memory"); + std::ignore = luaL_error(L, "init_keepers() failed while creating keeper states; out of memory"); return; } @@ -672,64 +675,68 @@ void init_keepers( Universe* U, lua_State* L) // we can trigger a GC from inside keeper_call(), where a keeper is acquired // from there, GC can collect a linda, which would acquire the keeper again, and deadlock the thread. // therefore, we need a recursive mutex. - MUTEX_RECURSIVE_INIT( &U->keepers->keeper_array[i].keeper_cs); + MUTEX_RECURSIVE_INIT(&U->keepers->keeper_array[i].keeper_cs); - STACK_CHECK( K, 0); + STACK_CHECK(K, 0); // copy the universe pointer in the keeper itself - universe_store( K, U); - STACK_MID( K, 0); + universe_store(K, U); + STACK_MID(K, 0); // make sure 'package' is initialized in keeper states, so that we have require() // this because this is needed when transferring deep userdata object - luaL_requiref( K, "package", luaopen_package, 1); // package - lua_pop( K, 1); // - STACK_MID( K, 0); - serialize_require( DEBUGSPEW_PARAM_COMMA( U) K); - STACK_MID( K, 0); + luaL_requiref(K, "package", luaopen_package, 1); // package + lua_pop(K, 1); // + STACK_MID(K, 0); + serialize_require(DEBUGSPEW_PARAM_COMMA(U) K); + STACK_MID(K, 0); // copy package.path and package.cpath from the source state - lua_getglobal( L, "package"); // "..." keepersUD package - if( !lua_isnil( L, -1)) + lua_getglobal(L, "package"); // "..." keepersUD package + if (!lua_isnil(L, -1)) { // when copying with mode eLM_ToKeeper, error message is pushed at the top of the stack, not raised immediately - if( luaG_inter_copy_package( U, L, K, -1, eLM_ToKeeper)) + if (luaG_inter_copy_package(U, L, K, -1, eLM_ToKeeper)) { // if something went wrong, the error message is at the top of the stack - lua_remove( L, -2); // error_msg - (void) lua_error( L); + lua_remove(L, -2); // error_msg + (void) lua_error(L); return; } } - lua_pop( L, 1); // - STACK_MID( L, 0); + lua_pop(L, 1); // + STACK_MID(L, 0); // attempt to call on_state_create(), if we have one and it is a C function // (only support a C function because we can't transfer executable Lua code in keepers) // will raise an error in L in case of problem - call_on_state_create( U, K, L, eLM_ToKeeper); + call_on_state_create(U, K, L, eLM_ToKeeper); // to see VM name in Decoda debugger - lua_pushfstring( K, "Keeper #%d", i + 1); // "Keeper #n" - lua_setglobal( K, "decoda_name"); // + lua_pushfstring(K, "Keeper #%d", i + 1); // "Keeper #n" + lua_setglobal(K, "decoda_name"); // // create the fifos table in the keeper state - FIFOS_KEY.set_registry(K, [](lua_State* L) { lua_newtable(L); } ); - STACK_END( K, 0); + FIFOS_KEY.set_registry(K, [](lua_State* L) { lua_newtable(L); }); + STACK_END(K, 0); } - STACK_END( L, 0); + STACK_END(L, 0); } +// ################################################################################################## + // should be called only when inside a keeper_acquire/keeper_release pair (see linda_protected_call) Keeper* which_keeper(Keepers* keepers_, ptrdiff_t magic_) { - int const nbKeepers = keepers_->nb_keepers; + int const nbKeepers{ keepers_->nb_keepers }; unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); return &keepers_->keeper_array[i]; } -Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_) +// ################################################################################################## + +Keeper* keeper_acquire(Keepers* keepers_, ptrdiff_t magic_) { - int const nbKeepers = keepers_->nb_keepers; + int const nbKeepers{ keepers_->nb_keepers }; // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) if( nbKeepers == 0) { @@ -753,36 +760,45 @@ Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_) } } -void keeper_release( Keeper* K) +// ################################################################################################## + +void keeper_release(Keeper* K) { //-- K->count; - if( K) MUTEX_UNLOCK( &K->keeper_cs); + if (K) + { + MUTEX_UNLOCK(&K->keeper_cs); + } } -void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mode_) +// ################################################################################################## + +void keeper_toggle_nil_sentinels(lua_State* L, int val_i_, LookupMode const mode_) { - int i, n = lua_gettop( L); - for( i = val_i_; i <= n; ++ i) + int const n{ lua_gettop(L) }; + for (int i = val_i_; i <= n; ++i) { - if( mode_ == eLM_ToKeeper) + if (mode_ == eLM_ToKeeper) { - if( lua_isnil( L, i)) + if (lua_isnil(L, i)) { NIL_SENTINEL.push(L); - lua_replace( L, i); + lua_replace(L, i); } } else { if (NIL_SENTINEL.equals(L, i)) { - lua_pushnil( L); - lua_replace( L, i); + lua_pushnil(L); + lua_replace(L, i); } } } } +// ################################################################################################## + /* * Call a function ('func_name') in the keeper state, and pass on the returned * values to 'L'. @@ -794,31 +810,31 @@ void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mod */ int keeper_call(Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, void* linda, int starting_index) { - int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0; - int const Ktos = lua_gettop( K); + int const args{ starting_index ? (lua_gettop(L) - starting_index + 1) : 0 }; + int const Ktos{ lua_gettop(K) }; int retvals = -1; - STACK_GROW( K, 2); + STACK_GROW(K, 2); - PUSH_KEEPER_FUNC( K, func_); + PUSH_KEEPER_FUNC(K, func_); - lua_pushlightuserdata( K, linda); + lua_pushlightuserdata(K, linda); - if( (args == 0) || luaG_inter_copy( U, L, K, args, eLM_ToKeeper) == 0) // L->K + if ((args == 0) || luaG_inter_copy(U, L, K, args, eLM_ToKeeper) == 0) // L->K { - lua_call( K, 1 + args, LUA_MULTRET); + lua_call(K, 1 + args, LUA_MULTRET); - retvals = lua_gettop( K) - Ktos; + retvals = lua_gettop(K) - Ktos; // note that this can raise a luaL_error while the keeper state (and its mutex) is acquired // this may interrupt a lane, causing the destruction of the underlying OS thread // after this, another lane making use of this keeper can get an error code from the mutex-locking function // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) - if( (retvals > 0) && luaG_inter_move( U, K, L, retvals, eLM_FromKeeper) != 0) // K->L + if ((retvals > 0) && luaG_inter_move(U, K, L, retvals, eLM_FromKeeper) != 0) // K->L { retvals = -1; } } // whatever happens, restore the stack to where it was at the origin - lua_settop( K, Ktos); + lua_settop(K, Ktos); return retvals; } diff --git a/src/keeper.h b/src/keeper.h index ce9742a..5f52fa0 100644 --- a/src/keeper.h +++ b/src/keeper.h @@ -19,7 +19,7 @@ struct Keeper { MUTEX_T keeper_cs; lua_State* L; - //int count; + // int count; }; struct Keepers @@ -28,30 +28,30 @@ struct Keepers Keeper keeper_array[1]; }; -void init_keepers( Universe* U, lua_State* L); -void close_keepers( Universe* U); - -Keeper* which_keeper( Keepers* keepers_, ptrdiff_t magic_); -Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_); -#define KEEPER_MAGIC_SHIFT 3 -void keeper_release( Keeper* K); -void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mode_); -int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_); - +static constexpr ptrdiff_t KEEPER_MAGIC_SHIFT{ 3 }; // crc64/we of string "NIL_SENTINEL" generated at http://www.nitrxgen.net/hashgen/ static constexpr UniqueKey NIL_SENTINEL{ 0x7eaafa003a1d11a1ull }; +void init_keepers(Universe* U, lua_State* L); +void close_keepers(Universe* U); + +Keeper* which_keeper(Keepers* keepers_, ptrdiff_t magic_); +Keeper* keeper_acquire(Keepers* keepers_, ptrdiff_t magic_); +void keeper_release(Keeper* K); +void keeper_toggle_nil_sentinels(lua_State* L, int val_i_, LookupMode const mode_); +int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_); + using keeper_api_t = lua_CFunction; -#define KEEPER_API( _op) keepercall_ ## _op +#define KEEPER_API(_op) keepercall_##_op #define PUSH_KEEPER_FUNC lua_pushcfunction -// lua_Cfunctions to run inside a keeper state (formerly implemented in Lua) -int keepercall_clear( lua_State* L); -int keepercall_send( lua_State* L); -int keepercall_receive( lua_State* L); -int keepercall_receive_batched( lua_State* L); -int keepercall_limit( lua_State* L); -int keepercall_get( lua_State* L); -int keepercall_set( lua_State* L); -int keepercall_count( lua_State* L); +// lua_Cfunctions to run inside a keeper state +int keepercall_clear(lua_State* L); +int keepercall_send(lua_State* L); +int keepercall_receive(lua_State* L); +int keepercall_receive_batched(lua_State* L); +int keepercall_limit(lua_State* L); +int keepercall_get(lua_State* L); +int keepercall_set(lua_State* L); +int keepercall_count(lua_State* L); int keeper_call(Universe* U, lua_State* K, keeper_api_t _func, lua_State* L, void* linda, int starting_index); diff --git a/src/lanes.cpp b/src/lanes.cpp index 1589240..38dd92c 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp @@ -2076,7 +2076,7 @@ static void EnableCrashingOnCrashes( void) while( !s_ecoc_go_ahead) { Sleep(1); } // changes threads } } -#endif // PLATFORM_WIN32 +#endif // PLATFORM_WIN32 && !defined NDEBUG LANES_API int luaopen_lanes_core( lua_State* L) { diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 67213bc..9982693 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h @@ -5,6 +5,7 @@ extern "C" { #endif // __cplusplus #include "lua.h" #include "lualib.h" +#include "lauxlib.h" #ifdef __cplusplus } #endif // __cplusplus @@ -78,6 +79,10 @@ extern char const* debugspew_indent; #define ASSERT_L(c) _ASSERT_L(L,c) -#define STACK_GROW( L, n) do { if (!lua_checkstack(L,(int)(n))) luaL_error( L, "Cannot grow stack!" ); } while( 0) +inline void STACK_GROW(lua_State* L, int n_) +{ + if (!lua_checkstack(L, n_)) + luaL_error(L, "Cannot grow stack!"); +} #define LUAG_FUNC( func_name) int LG_##func_name( lua_State* L) diff --git a/src/platform.h b/src/platform.h index ce621d9..b10f0ad 100644 --- a/src/platform.h +++ b/src/platform.h @@ -6,6 +6,7 @@ #define PLATFORM_XBOX #elif (defined _WIN32) #define PLATFORM_WIN32 + #define NOMINMAX #elif (defined __linux__) #define PLATFORM_LINUX #elif (defined __APPLE__) && (defined __MACH__) -- cgit v1.2.3-55-g6feb