lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Haven't got any ideas on the thread front but for locking the data
here's what I suggest base on the 1 writer, many readers concept

_M[...] = ud
_M:swap()
in lua code then something like this in C:

size_t luaIndexOfProtectedPtr( lua *L, char const *name );
void const*  luaLockProtectedPointer( lua *L, size_t index ); /* Try
to lock the pointer */
void const*  luaWaitProtectedPointer( lua *L, size_t index ); /* Wait
until get the pointer, no time limit */
void const*  luaTimeProtectedPointer( lua *L, size_t index, clock_t
tics ); /* Wait until get the pointer, time limited */
void const*  luaSpinProtectedPointer( lua *L, size_t index, size_t
spins ); /* Try X times to get the pointer */
void luaFreeProtectedPointer( lua *L, size_t index );

Then the swap can check to see if the number of locks is 0, if so then
it swaps, releases the lua's internal lock and returns to normal
execution.

On Mon, 24 Apr 2023 at 10:19, Sergey Kovalev <kovserg33@gmail.com> wrote:
>
> You can use C stackless coroutinues:
>
> Here is simple example: ( https://cloud.mail.ru/public/Name/jLstqLvyk )
>
> [[example.c]]
>
> #include "lauxlib.h"
> #include <stdio.h>
>
> #ifdef __GNUC__
> #define EXPORT
> #else
> #define EXPORT __declspec(dllexport)
> #endif
>
> //------------------------------------------------------------------------------
>
> #define DECL_LUA_KFN(Name,CtxType) \
>     static int lua_##Name##_kfn(lua_State* L, int status, lua_KContext kctx) { \
>         CtxType *ctx=(CtxType*)kctx; \
>         if (Name##_loop(ctx,L)) { \
>         lua_settop(L,0); return lua_yieldk(L, 0, kctx, lua_##Name##_kfn); \
>         } \
>         Name##_done(ctx,L); lua_settop(L,0); return 0; \
>     } \
>     static int lua_##Name##_start(lua_State* L) { \
>         CtxType *ctx=(CtxType*)lua_touserdata(L,lua_upvalueindex(1)); \
>     return lua_##Name##_kfn(L,1,(lua_KContext)ctx); \
>     } \
>     static int lua_##Name##_gc(lua_State* L) { \
>         CtxType *ctx=(CtxType*)lua_touserdata(L,1); \
>         Name##_done(ctx,L); return 0; \
>     } \
>     static int lua_##Name(lua_State* L) { \
>         lua_State* co = lua_newthread(L); \
>         CtxType *ctx=(CtxType*)lua_newuserdata(co,sizeof(CtxType)); \
>         Name##_init(ctx,L); \
>         lua_newtable(co); \
>         lua_pushstring(co, "__gc"); \
>         lua_pushcfunction(co, lua_##Name##_gc); \
>         lua_settable(co,-3); \
>         lua_setmetatable(co, -2); \
>         lua_pushcclosure(co,lua_##Name##_start,1); \
>         return 1; \
>     }
>
> //------------------------------------------------------------------------------
>
> typedef struct Seq { int line; } Seq;
>
> #define SEQ_RESET(seq) { Seq *_seq=(seq); _seq->line=0; }
> #define SEQ_BEGIN(seq) { Seq *_seq=(seq); _seq_switch: switch(_seq->line) { \
>     default: _seq->line=-2; case -2: return 0; _seq->line=0; case 0: {} {
> #define SEQ_NEXT  { _seq->line=__LINE__; goto _seq_next; case __LINE__: {} }
> #define SEQ_STOP  { goto _seq_done; }
> #define SEQ_RETRY { goto _seq_next; }
> #define SEQ_END   } _seq_done: _seq->line=-1; case -1: return 0;\
>     } _seq_next: return 1; }
>
> //------------------------------------------------------------------------------
>
> typedef struct MyfnState {
>     int alive; Seq seq[1];
>     int i,n;
> } MyfnState;
>
> static void mykfn_init(MyfnState *self,lua_State* L) {
>     self->alive=1;
>     self->n=lua_tointeger(L,1);
>     SEQ_RESET(self->seq)
>     printf("fn5_init n=%d\n",self->n);
> }
> static void mykfn_done(MyfnState *self,lua_State* L) {
>     if (self->alive) {
>     self->alive=0;
>     printf("fn5_done n=%d %s ", self->n,
>         self->seq->line<0 ? "finished":"not finished");
>     } else {
>         //printf("fn5_gc after done\n");
>     }
> }
> static int mykfn_loop(MyfnState *self,lua_State* L) {
>     SEQ_BEGIN(self->seq)
>     printf("first step ");
>     SEQ_NEXT
>     for(self->i=0;self->i<self->n;self->i++) {
>         printf("step i=%d ",self->i);
>         SEQ_NEXT
>     }
>     printf("last step ");
>     SEQ_END
> }
> DECL_LUA_KFN(mykfn,MyfnState)
>
> //------------------------------------------------------------------------------
>
> int EXPORT luaopen_example(lua_State* L) {
>     lua_register(L, "mykfn",  lua_mykfn);
>     return 0;
> }
>
> [[ test-kfn.lua ]]
>
> require "example"
>
> do
>     local c1=mykfn(5)
>     local c2=mykfn(9)
>     for i=1,7 do
>     io.write(i.."\t")
>     coroutine.resume(c1)
>     coroutine.resume(c2)
>     print(coroutine.status(c1),coroutine.status(c2))
>     end
> end
> print"--gc--"
> collectgarbage "collect"
> print""
> print"--done--"
>
> [[ build.sh ]]
>
> gcc -shared -o example.so example.c
>
> [[ output ]]
>
> fn5_init n=5
> fn5_init n=9
> 1    first step first step suspended    suspended
> 2    step i=0 step i=0 suspended    suspended
> 3    step i=1 step i=1 suspended    suspended
> 4    step i=2 step i=2 suspended    suspended
> 5    step i=3 step i=3 suspended    suspended
> 6    step i=4 step i=4 suspended    suspended
> 7    last step fn5_done n=5 finished step i=5 dead    suspended
> --gc--
> fn5_done n=9 not finished
> --done--
>
>
> вт, 28 мар. 2023 г. в 09:41, Marc Balmer <marc@msys.ch>:
>>
>>
>>
>>
>> I don’t know if it was ever discussed, that when you call C functions in Lua coroutines, the whole Lua system is blocked, i.e., no coroutine can advance.
>> Currently there is no way to yield from C. This behavior is problematic for time critical applications, e.g., as in our application, the execution environment for machine sequences.
>>
>> We implemented a way to yield from C, i.e., only the coroutine executing the long running C code is blocked.
>> As a solution, we create a coroutine in the interpreter (C code) for each coroutine in the Lua code. We applied the solution to the blocking C functions in “io” and “os” (liolib.c and loslib.c).
>> Of course, we are aware, that this cannot be a general solution, as existing code would not expect yields from these libraries. Maybe a separate library with functions to yield from C would be a good approach.
>> The yield from C feature makes most sense for custom, application specific C libraries.
>> I think that the possibility to yield from C would be a useful feature for the interpreter, because not the whole Lua system needs to block when a long running C function is executed.
>> Please let me know what you think about this feature.
>>
>>
>> There are, fwiw, lua_yieldk() and lua_yield() in the C API.
>>
>> - mb
>>