You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
LCUI_FUNCvoidlcuM_addmyawaitf (lua_State*L) {
staticconstluaL_Regmodf[] = {
{"myawait", lua_myawait},
{NULL, NULL}
};
lcuM_setfuncs(L, modf, LCU_MODUPVS);
}
staticintlua_myawait (lua_State*L) {
lcu_Scheduler*sched=lcu_getsched(L); /* requires 'LCU_MODUPVS' upvalues */returnlcuT_resetcoreqk(L, sched, k_setupfunc, onreturn, cancancel);
}
staticintk_setupfunc (lua_State*L,
uv_req_t*request,
uv_loop_t*loop,
lcu_Operation*op) {
uv_myevent_t*myevent= (uv_myevent_t*)request;
/* check argments and obtain desired configs for myevent *//* leave on the stack values required to produce the results */interr=uv_myevent(loop, myevent, uv_onmyevent, /* configs */);
lcuT_armcoreq(L, loop, op, err);
if (err<0) returnlcuL_pusherrres(L, err);
return-1; /* yield on success */
}
/* optional, if is 'NULL' behaves as 'return 1' */staticintcancancel (lua_State*L) {
/* we know the thread is not awaiting for this myevent anymore *//* inpect any global state that might need clean up */if (/* we still need 'uv_onmyevent' to be called for some clean up */)
return0;
elsereturn1;
}
staticvoiduv_onmyevent (uv_myevent_t*myrequest, /* myevent details */) {
uv_loop_t*loop=myrequest->loop;
uv_req_t*request= (uv_req_t*)myrequest;
lua_State*thread=lcuU_endcoreq(loop, request);
if (thread) {
/* push values to yield to 'thread', for 'onreturn' to process */lcuU_resumecoreq(loop, request, /* number of pushed values */);
} else {
/* request wasn't canceled, we can do the clean up now */
}
}
/* optional, if is 'NULL' behaves as 'return lua_gettop(L)' */staticintonreturn (lua_State*L) {
/* use values left on the stack by 'k_setupfunc' and the ones yielded *//* by 'uv_onmyevent' to produce the values to be returned */return/* number of values to return from the top of the stack */;
}
Coroutine Handle Operation (cohdl)
LCUI_FUNCvoidlcuM_addmyawaitf (lua_State*L) {
staticconstluaL_Regmodf[] = {
{"myawait", lua_myawait},
{NULL, NULL}
};
lcuM_setfuncs(L, modf, LCU_MODUPVS);
}
staticintlua_myawait (lua_State*L) {
lcu_Scheduler*sched=lcu_getsched(L); /* requires 'LCU_MODUPVS' upvalues */returnlcuT_resetcohdlk(L, UV_MYEVENT, sched, k_setupfunc, onreturn, cancancel);
}
staticintk_setupfunc (lua_State*L,
uv_handle_t*handle,
uv_loop_t*loop,
lcu_Operation*op) {
uv_myevent_t*myevent= (uv_myevent_t*)handle;
/* check argments and obtain desired configs for myevent *//* leave on the stack values required to produce the results */interr=0;
if (loop) err=lcuT_armcohdl(L, op, uv_myevent_init(loop, myevent));
elseif (/* myevent is misconfigured? */) err=uv_myevent_stop(myevent);
elsereturn-1; /* yield on success */if (err >= 0) err=uv_myevent_start(myevent, uv_onmyevent, /* configs */);
if (err<0) returnlcuL_pusherrres(L, err);
return-1; /* yield on success */
}
/* optional, if is 'NULL' behaves as 'return 1' */staticintcancancel (lua_State*L) {
/* we know the thread is not awaiting for this myevent anymore *//* inpect any global state that might need clean up */if (/* we still need 'uv_onmyevent' to be called for some clean up */)
return0;
elsereturn1;
}
staticvoiduv_onmyevent (uv_myevent_t*handle, /* myevent details */) {
if (lcuU_endcohdl(handle)) {
lua_State*thread= (lua_State*)handle->data;
/* push values to yield to 'thread', for 'onreturn' to process */lcuU_resumecohdl((uv_handle_t*)handle, /* number of pushed values */);
} else {
/* 'cancancel' returned 0, and we can do the clean up now */
}
}
/* optional, if is 'NULL' behaves as 'return lua_gettop(L)' */staticintonreturn (lua_State*L) {
/* use values left on the stack by 'k_setupfunc' and the ones yielded *//* by 'uv_onmyevent' to produce the values to be returned */return/* number of values to return from the top of the stack */;
}
Userdata Handle Operation (udhdl)
#defineMYOBJECT_CLASS LCU_PREFIX"MyObject"
LCUI_FUNCvoidlcuM_addmyawaitf (lua_State*L) {
staticconstluaL_Regmetf[] = {
{"__gc", myobj_gc},
{"__close", myobj_gc},
{"close", myobj_close},
{"await", myobj_await},
{NULL, NULL}
};
staticconstluaL_Regmodf[] = {
{"myobject", lua_myobject},
{NULL, NULL}
};
/* create object metatable */luaL_newmetatable(L, MYOBJECT_CLASS);
lcuL_setfuncs(L, metf, 0);
lua_pop(L, 1);
/* add object creation function to 'coutil.system' */lcuM_setfuncs(L, modf, LCU_MODUPVS);
}
typedefstructMyObject {
/* same fields from 'lcu_UdataHandle' */intflags;
lcu_HandleActionstop;
lua_CFunctionstep;
uv_myobject_thandle; /* is 'uv_handle_t' in 'lcu_UdataHandle' *//* any extra fields */
} MyObject;
staticintlua_myobject (lua_State*L) {
lcu_Scheduler*sched=lcu_getsched(L); /* requires 'LCU_MODUPVS' upvalues */MyObject*myobj=lcuT_newudhdl(L, MyObject, MYOBJECT_CLASS);
/* check argments and obtain desired configs for 'myobj' */interr=uv_myobject_init(loop, lcu_ud2hdl(myobj), /* configs */);
if (err<0) returnlcuL_pusherrres(L, err);
/* initialize any extra fields */return1;
}
staticintmyobj_close (lua_State*L) {
MyObject*myobj= (MyObject*)luaL_checkudata(L, 1, MYOBJECT_CLASS);
luaL_argcheck(L, !lcuL_maskflag(udhdl, LCU_HANDLECLOSEDFLAG), 1, "closed object");
lcu_closeudhdl(L, 1);
/* free any extra fields that can be released before 'uv_myobject_t' is closed */lua_pushboolean(L, 1);
return1;
}
staticintmyobj_gc (lua_State*L) {
luaL_checkudata(L, 1, MYOBJECT_CLASS);
lcu_closeudhdl(L, 1);
/* free any remaining extra fields */return0;
}
staticintmyobj_await (lua_State*L) {
lcu_UdataHandle*udhdl= (lcu_UdataHandle*)luaL_checkudata(L, 1, MYOBJECT_CLASS);
luaL_argcheck(L, !lcuL_maskflag(udhdl, LCU_HANDLECLOSEDFLAG), 1, "closed object");
returnlcuT_resetudhdlk(L, udhdl, startmyawait, stopmyawait, onreturn);
}
staticintstartmyawait (uv_handle_t*handle) {
returnuv_myobj_myevent_start((uv_myobject_t*)handle, uv_onmyevent);
}
staticintstopmyawait (uv_handle_t*handle) {
returnuv_myobj_myevent_stop((uv_myobject_t*)handle);
}
staticvoiduv_onmyevent (uv_myobject_t*myobjhdl, /* myevent details */) {
uv_handle_t*handle= (uv_handle_t*)myobjhdl;
lua_State*thread= (lua_State*)handle->data;
lcu_assert(thread);
/* push values to yield to 'k_onreturn' */lcuU_resumeudhdl(handle, /* number of pushed values */);
}
staticintonreturn (lua_State*L) {
/* use values left on the stack by 'myobj_await' and the ones yielded *//* by 'uv_onmyevent' to produce the values to be returned */return/* number of values to return from the top of the stack */;
}
Userdata Request Operation (udreq)
#defineMYOBJECT_CLASS LCU_PREFIX"MyObject"
LCUI_FUNCvoidlcuM_addmyawaitf (lua_State*L) {
staticconstluaL_Regmetf[] = {
{"__gc", myobj_gc},
{"__close", myobj_gc},
{"close", myobj_close},
{NULL, NULL}
};
staticconstluaL_Regupvf[] = {
{"awaitmyobj", lua_awaitmyobj},
{NULL, NULL}
};
staticconstluaL_Regmodf[] = {
{"myobject", lua_myobject},
{NULL, NULL}
};
/* create object metatable */luaL_newmetatable(L, MYOBJECT_CLASS);
lcuL_setfuncs(L, metf, 0);
lua_pop(L, 1);
/* add object await function to 'coutil.system' */lcuM_setfuncs(L, upvf, LCU_MODUPVS);
/* add object creation function to 'coutil.system' */lcuM_setfuncs(L, modf, 0);
}
typedefstructMyObject {
/* same fields from 'lcu_UdataRequest' */lua_CFunctionresults;
lua_CFunctioncancel;
uv_myevent_tmyevent; /* is 'uv_req_t' in 'lcu_UdataRequest' *//* any extra fields */
} MyObject;
staticintlua_myobject (lua_State*L) {
MyObject*myobj=lcuT_newudreq(L, MyObject);
/* initialize any extra fields */luaL_setmetatable(L, MYOBJECT_CLASS);
return1;
}
staticintmyobj_close (lua_State*L) {
MyObject*myobj= (MyObject*)luaL_checkudata(L, 1, MYOBJECT_CLASS);
luaL_argcheck(L, myobj->myevent.type==UV_MYEVENT, 1, "pending request");
myobj_gc(L);
lua_pushboolean(L, 1);
return1;
}
staticintmyobj_gc (lua_State*L) {
MyObject*myobj= (MyObject*)luaL_checkudata(L, 1, MYOBJECT_CLASS);
if (myobj->myevent.type==UV_MYEVENT) /* mark 'myobj' as pending to be freed */else/* free any extra fields */return0;
}
staticintlua_awaitmyobj (lua_State*L) {
lcu_Scheduler*sched=lcu_getsched(L); /* requires 'LCU_MODUPVS' upvalues */MyObject*myobj= (MyObject*)luaL_checkudata(L, 1, MYOBJECT_CLASS);
luaL_argcheck(L, myobj->myevent.data==NULL, 1, "already in use");
luaL_argcheck(L, myobj->myevent.type==UV_MYEVENT, 1, "still pending");
returnlcuT_resetudreqk(L, sched, (lcu_UdataRequest*)myobj, k_setupfunc, onreturn, cancancel);
}
staticintk_setupfunc (lua_State*L, uv_req_t*request, uv_loop_t*loop) {
MyObject*myobj= (MyObject*)lua_touserdata(L, 1);
/* check argments and obtain desired configs for myevent *//* leave on the stack values required to produce the results */interr=uv_myevent(loop, &myobj->myevent, uv_onmyevent, /* configs */);
if (err<0) returnlcuL_pusherrres(L, err);
return-1; /* yield on success */
}
/* optional, if is 'NULL' behaves as 'return 1' */staticintcancancel (lua_State*L) {
/* we know the thread is not awaiting for this myevent anymore *//* inpect any global state that might need clean up */if (/* we still need 'uv_onmyevent' to be called for some clean up */)
return0;
elsereturn1;
}
staticvoiduv_onmyevent (uv_myevent_t*myevent, /* myevent details */) {
uv_loop_t*loop=myevent->loop;
uv_req_t*request= (uv_req_t*)myevent;
lua_State*thread=lcuU_endudreq(loop, request);
if (thread) {
/* push values to yield to 'thread', for 'onreturn' to process */lcuU_resumeudreq(loop, request, /* number of pushed values */);
} else {
/* request wasn't canceled, we can do the clean up now */
}
if (/* 'myobj' was marked as pending to be freed */)
/* free any extra fields */
}
/* optional, if is 'NULL' behaves as 'return lua_gettop(L)' */staticintonreturn (lua_State*L) {
/* use values left on the stack by 'k_setupfunc' and the ones yielded *//* by 'uv_onmyevent' to produce the values to be returned */return/* number of values to return from the top of the stack */;
}
Data Structure States
Coroutine Operation
Name
R
S
P
C
lua_KFunction
Callback Pending
Freed Operation
R
Awaiting Request Op.
R
S
P
k_endop
uv_<request>_cb
Completed Request Op.
R
S
Canceled Request Op.
R
S
?
uv_<request>_cb
Reseting Request Op.
R
S
P
?
k_resetopk
uv_<request>_cb
Awaiting Handle Op.
P
k_endop
uv_<handle>_cb
Completed Handle Op.
uv_<handle>_cb
Canceled Handle Op.
C
uv_<handle>_cb
Reseting Canceled Handle Op.
P
C
k_resetopk
uv_<handle>_cb
Closing Handle Op.
closedhdl:uv_close_cb
Reseting Closed Handle Op.
P
k_resetopk
closedhdl:uv_close_cb
R: FLAG_REQUEST is set in coroutines's Operation.flags.
S: FLAG_THRSAVED is set in coroutines's Operation.flags.
P: FLAG_PENDING is set in coroutines's Operation.flags.
C: FLAG_CLEANUP is set in coroutines's Operation.flags.
Userdata Handle
Name
S
P
C
lua_KFunction
Callback Pending
Ready
Closing
C
closedobj:uv_close_cb
Freed
C
Awaiting
S
P
k_endobjopk
uv_<handle>_cb
Completed
S
S: (started) stop and step fields are not NULL in lcu_UdataHandle.
P: (pending) handle.data is not NULL in lcu_UdataHandle.
C: (closed) LCU_HANDLECLOSEDFLAG is set in lcu_UdataHandle.flags.
Userdata Request
Name
F
S
P
lua_KFunction
Callback Pending
Freed
F
Awaiting
P
k_endudreq
uv_<request>_cb
Completed
S
Canceled
uv_<request>_cb
Reseting
P
k_resetudreqk
uv_<request>_cb
F: (freed) request.type is UV_UNKNOWN_REQ in lcu_UdataRequest.
S: (saved) request.type is UV_REQ_TYPE_MAX in lcu_UdataRequest.
P: (pending) request.data is not NULL in lcu_UdataRequest.