@@ -415,8 +415,7 @@ namespace netxs::events
415415 indexer.script_param = std::ref ((T&)param);
416416
417417 auto error = faux;
418- auto [ok, lua_fx_id] = push_function_id (script_body);
419- if (ok)
418+ if (push_function_id (script_body))
420419 {
421420 if (::lua_rawget (lua, -2 ) == LUA_TFUNCTION) // It is precompiled.
422421 {
@@ -469,7 +468,19 @@ namespace netxs::events
469468 log (ansi::clr (yellowlt, shadow), " \n " , prompt::lua, result);
470469 script.cmd = utf::concat (shadow, " \n " , prompt::lua, result);
471470 }
472- std::pair<bool , view> luna::push_function_id (view script_body)
471+ // Return the length of the stack top table.
472+ si32 luna::get_table_size ()
473+ {
474+ auto count = 0 ;
475+ ::lua_pushnil (lua); // Push nil to start the iteration.
476+ while (::lua_next (lua, -2 ) != 0 )
477+ {
478+ count++; // Key is at -2, value at -1.
479+ ::lua_pop (lua, 1 ); // Pop the value, leaving the key for the next iteration.
480+ }
481+ return count;
482+ }
483+ bool luna::push_function_id (view script_body)
473484 {
474485 ::lua_settop (lua, 0 );
475486 // Get a table of precompiled functions from the registry.
@@ -481,64 +492,67 @@ namespace netxs::events
481492 auto lua_fx_id = view{ memory_id, sizeof (script_id) };
482493 // if constexpr (debugmode) log("Function id='%%'", utf::debase437(lua_fx_id));
483494 ::lua_pushlstring (lua, lua_fx_id.data(), lua_fx_id.size());
484- return std::pair{ true , lua_fx_id } ;
495+ return true ;
485496 }
486497 else
487498 {
488499 log (" %%The table of precompiled functions is missing" , prompt::lua);
489500 ::lua_settop (lua, 0 );
490- return std::pair{ faux, view{} } ;
501+ return faux;
491502 }
492503 }
493- bool luna::precompile_function (sptr<text>& script_body_ptr)
504+ void luna::precompile_function (sptr<std::pair<ui64, text> >& script_body_ptr)
494505 {
495- auto precompiled = faux;
496- if (script_body_ptr && script_body_ptr->size ())
506+ if (script_body_ptr)
497507 {
498- auto & script_body = *script_body_ptr;
499- auto [ok, lua_fx_id] = push_function_id (script_body);
500- if (ok)
508+ auto & [ref_count, script_body] = *script_body_ptr;
509+ if (script_body.size ())
501510 {
502- if (:: lua_rawget (lua, - 2 ) == LUA_TFUNCTION) // It is already precompiled.
511+ if (push_function_id (script_body))
503512 {
504- // if constexpr (debugmode) log("The script is already precompiled");
505- precompiled = true ;
506- }
507- else // It is not precompiled yet.
508- {
509- ::lua_pop (lua, 1 ); // Pop nil after the ::lua_rawget() call.
510- ::lua_pushlstring (lua, lua_fx_id.data(), lua_fx_id.size()); // Push fx id again.
511- auto error = ::luaL_loadbuffer (lua, script_body.data (), script_body.size (), " precompilation" );
512- if (error)
513+ ::lua_pushvalue (lua, -1 ); // Duplicate lua_fx_id string.
514+ if (::lua_rawget (lua, -3 ) == LUA_TFUNCTION) // It is already precompiled.
513515 {
514- auto result = ::lua_tostring (lua, -1 );
515- log (" %%Precompilation error: %msg%" , prompt::lua, ansi::err (result));
516- ::lua_pop (lua, 1 ); // Pop error message from stack.
516+ // if constexpr (debugmode) log("The script is already precompiled");
517+ ++ref_count;
517518 }
518- else
519+ else // It is not precompiled yet.
519520 {
520- // if constexpr (debugmode) log("Script precompilation is done");
521- ::lua_rawset (lua, -3 );
522- precompiled = true ;
521+ ::lua_pop (lua, 1 ); // Pop nil after the ::lua_rawget() call.
522+ auto error = ::luaL_loadbuffer (lua, script_body.data (), script_body.size (), " precompilation" );
523+ if (error)
524+ {
525+ auto result = ::lua_tostring (lua, -1 );
526+ log (" %%Precompilation error: %msg%" , prompt::lua, ansi::err (result));
527+ ::lua_pop (lua, 1 ); // Pop error message from stack.
528+ }
529+ else
530+ {
531+ // if constexpr (debugmode) log("Script precompilation is done");
532+ ::lua_rawset (lua, -3 );
533+ // if constexpr (debugmode) log("Add: Precompiled function counter: %%", get_table_size());
534+ ++ref_count;
535+ }
523536 }
537+ ::lua_settop (lua, 0 );
524538 }
525- ::lua_settop (lua, 0 );
526539 }
527540 }
528- return precompiled;
529541 }
530- void luna::remove_function (sptr<text>& script_body_ptr)
542+ void luna::remove_function (sptr<std::pair<ui64, text> >& script_body_ptr)
531543 {
532- if (script_body_ptr && script_body_ptr-> size () && script_body_ptr. use_count () == 1 )
544+ if (script_body_ptr)
533545 {
534- auto & script_body = *script_body_ptr;
535- auto [ok, lua_fx_id] = push_function_id (script_body);
536- if (ok)
546+ auto & [ref_count, script_body] = *script_body_ptr;
547+ if (ref_count && --ref_count == 0 )
537548 {
538- ::lua_pushnil (lua);
539- ::lua_rawset (lua, -3 );
540- ::lua_settop (lua, 0 );
541- // if constexpr (debugmode) log("Function id='%%' removed", utf::debase437(lua_fx_id));
549+ if (push_function_id (script_body))
550+ {
551+ ::lua_pushnil (lua);
552+ ::lua_rawset (lua, -3 ); // Remove rec from the table (because of nil) and pop key and val from stack.
553+ // if constexpr (debugmode) log("Drop: Precompiled function counter: %%", get_table_size());
554+ ::lua_settop (lua, 0 );
555+ }
542556 }
543557 }
544558 }
@@ -591,18 +605,16 @@ namespace netxs::events
591605 if (lua) ::lua_close (lua);
592606 }
593607
594- script_ref::script_ref (auth& indexer, context_t & context, sptr<text> script_body_ptr)
608+ script_ref::script_ref (auth& indexer, context_t & context, sptr<std::pair<ui64, text> > script_body_ptr)
595609 : indexer{ indexer },
596610 context{ context },
597- script_body_ptr{ script_body_ptr },
598- precompiled{ indexer.luafx .precompile_function (script_body_ptr) }
599- { }
611+ script_body_ptr{ script_body_ptr }
612+ {
613+ indexer.luafx .precompile_function (script_body_ptr);
614+ }
600615 script_ref::~script_ref ()
601616 {
602- if (precompiled)
603- {
604- indexer.luafx .remove_function (script_body_ptr);
605- }
617+ indexer.luafx .remove_function (script_body_ptr);
606618 }
607619
608620 auth::auth (bool use_timer)
0 commit comments