[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RES: LuaTask needs your help
- From: "Rafael - SosCpdTerra" <soscpd@...>
- Date: Sun, 8 Jul 2007 09:37:25 -0300
Think the end justify the way.
-----Mensagem original-----
De: lua-bounces@bazar2.conectiva.com.br
[mailto:lua-bounces@bazar2.conectiva.com.br] Em nome de Kacper Wysocki
Enviada em: domingo, 8 de julho de 2007 08:41
Para: Lua list
Assunto: Re: LuaTask needs your help
On 7/7/07, Daniel Quintela <dq@soongsoft.com> wrote:
>
> I'm almost ready to release LuaTask 1.6.2
>
> I changed the way TASK_ENTRY memory is allocated.
>
> I would appreciate it very much if you could test it and give me some
> feedback.
>
> You can get the candidate from: http://www.soongsoft.com/lua/ltask.c
I'd take a look but I can't reach this server...
-K
/* ** $Id: $ ** "Multitasking" support ( see README ) ** SoongSoft, Argentina **
http://www.soongsoft.com mailto:dq@soongsoft.com ** Copyright (C) 2003-2007
Daniel Quintela. All rights reserved. */ #include #include #include "lualib.h"
#ifdef _WIN32 # include # include # include #ifndef NATV_WIN32 #include #endif
#else # define _strdup strdup # define _strnicmp strncasecmp # include # include
# include # include # include # include # include #endif #define LT_NAMESPACE
"task" #include #include #include "syncos.h" #include "queue.h" #ifdef _WIN32
static long ( __stdcall *LRT_LIB_OVERRIDE)( lua_State *L) = NULL; static long (
__stdcall *LRT_DOFILE_OVERRIDE)( lua_State *L, const char *filename) = NULL;
#else long ( *LRT_LIB_OVERRIDE)( lua_State *L) = NULL; long (
*LRT_DOFILE_OVERRIDE)( lua_State *L, const char *filename) = NULL; #endif
#define TASK_SLOTS_STEP 16 typedef struct S_TASK_ENTRY { QUEUE queue; char
*fname; lua_State *L; OS_THREAD_T th; long running; char *id; long msgcount; }
TASK_ENTRY; typedef struct S_MSG_ENTRY { long len; long flags; char data[1]; }
MSG_ENTRY; typedef struct S_LOPN_LIB { char *name; unsigned long value; int
(*fnc)(lua_State *); } LOPN_LIB; static void * tlMutex = NULL; static TASK_ENTRY
* * volatile aTask; static long countTask = 0; static long threadDataKey; /*
Internal functions */ static OS_THREAD_FUNC taskthread( void *vp); static int
traceback (lua_State *L) { lua_getfield(L, LUA_GLOBALSINDEX, "debug"); if
(!lua_istable(L, -1)) { lua_pop(L, 1); return 1; } lua_getfield(L, -1,
"traceback"); if (!lua_isfunction(L, -1)) { lua_pop(L, 2); return 1; }
lua_pushvalue(L, 1); /* pass error message */ lua_pushinteger(L, 2); /* skip
this function and traceback */ lua_call(L, 2, 1); /* call debug.traceback */
return 1; } static int docall (lua_State *L, int narg, int clear) { int status;
int base = lua_gettop(L) - narg; /* function index */ lua_pushcfunction(L,
traceback); /* push traceback function */ lua_insert(L, base); /* put it under
chunk and args */ status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
lua_remove(L, base); /* remove traceback function */ /* force a complete garbage
collection in case of errors */ if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
return status; } static int dofile (lua_State *L, const char *name) { int status
= luaL_loadfile(L, name) || docall(L, 0, 1); return status; } static int
dostring (lua_State *L, const char *s, const char *name) { int status =
luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1); return status; }
static void taskCleanup( void *vp) { TASK_ENTRY *te = ( TASK_ENTRY *) vp;
lua_close( te->L); te->running = 0; te->L = NULL; free( te->fname); if( te->id
!= NULL) free( te->id); QueDestroy( &( te->queue)); } static long
int_taskcreate( const char *fname, lua_State *TL) { if( tlMutex != NULL) { long
i; OsLockMutex( tlMutex, INFINITE); for( i = 0; i < countTask; i++) if( !(
aTask[i]->running)) break; if( i == countTask) { TASK_ENTRY **te; long j; te = (
TASK_ENTRY * *) realloc( aTask, sizeof( TASK_ENTRY *) * ( countTask +
TASK_SLOTS_STEP)); if( te == NULL) { OsUnlockMutex( tlMutex); return( -1); }
aTask = te; aTask[i] = ( TASK_ENTRY *) malloc( sizeof( TASK_ENTRY) * (
TASK_SLOTS_STEP)); countTask += TASK_SLOTS_STEP; for( j = i; j < countTask; j++)
{ aTask[j] = ( TASK_ENTRY *) ( ( ( char * ) aTask[i] ) + ( sizeof( TASK_ENTRY) *
( j - i ) ) ); aTask[j]->running = 0; #ifdef NATV_WIN32 aTask[j]->th = 0; #endif
} } #ifdef NATV_WIN32 if( aTask[i]->th) CloseHandle( ( HANDLE) aTask[i]->th);
#endif if( ( aTask[i]->fname = _strdup( fname)) == NULL) { OsUnlockMutex(
tlMutex); return( -2); } else { if( QueCreate( &( aTask[i]->queue),
QUE_NO_LIMIT)) { free( aTask[i]->fname); OsUnlockMutex( tlMutex); return( -3); }
} aTask[i]->id = NULL; aTask[i]->msgcount = 0; aTask[i]->L = TL; if(
OsCreateThread( &( aTask[i]->th), taskthread, ( void *) i)) { free(
aTask[i]->fname); QueDestroy( &( aTask[i]->queue)); OsUnlockMutex( tlMutex);
return( -4); } aTask[i]->running = 1; OsUnlockMutex( tlMutex); return( i + 1); }
return( -11); } static long int_taskregister( const char *id) { long lrc = -1;
long i = ( long) OsGetThreadData( threadDataKey); if( ( i > -1) && ( i <
countTask)) { OsLockMutex( tlMutex, INFINITE); if( aTask[i]->id != NULL) free(
aTask[i]->id); aTask[i]->id = _strdup( id); lrc = 0; OsUnlockMutex( tlMutex); }
return( lrc); } static void int_tasklibinit(lua_State *L) { if( tlMutex == NULL)
{ threadDataKey = OsCreateThreadDataKey(); OsSetThreadData( threadDataKey, (
void *) 0); aTask = ( TASK_ENTRY * *) malloc( sizeof( TASK_ENTRY *) *
TASK_SLOTS_STEP); if( aTask != NULL) { long i; aTask[0] = ( TASK_ENTRY *)
malloc( sizeof( TASK_ENTRY) * TASK_SLOTS_STEP); countTask = TASK_SLOTS_STEP;
for( i = 0; i < TASK_SLOTS_STEP; i++) { aTask[i] = ( TASK_ENTRY *) ( ( ( char *
) aTask[0] ) + ( sizeof( TASK_ENTRY) * i ) ); aTask[i]->running = 0; #ifdef
NATV_WIN32 aTask[i]->th = 0; #endif } tlMutex = OsCreateMutex( NULL); QueCreate(
&( aTask[0]->queue), QUE_NO_LIMIT); aTask[0]->L = L; aTask[0]->running = 1;
aTask[0]->id = NULL; aTask[0]->fname = "_main_"; aTask[0]->msgcount = 0; }
#ifdef _WIN32 LRT_LIB_OVERRIDE = ( long ( __stdcall *)( lua_State *L))
GetProcAddress( GetModuleHandle( NULL), "_LRT_LIB_OVERRIDE@4");
LRT_DOFILE_OVERRIDE = ( long ( __stdcall *)( lua_State *L, const char
*filename)) GetProcAddress( GetModuleHandle( NULL), "_LRT_DOFILE_OVERRIDE@8");
#endif } } /* Registered functions */ static int reg_taskcreate(lua_State *L) {
long lrc; long ti = 0; const char *fname = luaL_checkstring(L, 1); lua_State *TL
= lua_open(); lua_newtable(TL); lua_pushnumber(TL, 0); lua_pushstring(TL,
fname); lua_settable( TL, -3); if( lua_istable(L, 2)) { lua_pushnil(L); while(
lua_next(L, 2) != 0) { if( lua_isnumber(L, -1)) { lua_pushnumber( TL, ++ti);
lua_pushnumber( TL, lua_tonumber( L, -1)); lua_settable( TL, -3); } else if(
lua_isstring(L, -1)) { lua_pushnumber( TL, ++ti); lua_pushstring( TL,
lua_tostring( L, -1)); lua_settable( TL, -3); } else { lua_pop(L, 1); break; }
lua_pop(L, 1); } } lua_setglobal(TL, "arg"); lrc = int_taskcreate( fname, TL);
if( lrc < 0) lua_close( TL); lua_pushnumber( L, lrc); return 1; } static int
reg_taskregister( lua_State *L) { long lrc; const char *id = luaL_checkstring(L,
1); lrc = int_taskregister( id); lua_pushnumber( L, lrc); return( 1); } static
int reg_taskfind( lua_State *L) { long i; long lrc = -1; const char *id =
luaL_checkstring(L, 1); OsLockMutex( tlMutex, INFINITE); for( i = 0; i <
countTask; i++) if( aTask[i]->id != NULL) if( !strcmp( aTask[i]->id, id)) { lrc
= i + 1; break; } OsUnlockMutex( tlMutex); lua_pushnumber( L, lrc); return( 1);
} static int reg_taskunregister(lua_State *L) { long lrc; lrc =
int_taskregister( ""); lua_pushnumber( L, lrc); return( 1); } static int
reg_taskpost(lua_State *L) { const char *buffer; MSG_ENTRY *me; size_t len; long
idx = ( long) luaL_checknumber(L, 1); long flags = ( long) luaL_optinteger(L, 3,
0); long lrc = -1; buffer = luaL_checklstring(L, 2, &len); idx--; OsLockMutex(
tlMutex, INFINITE); if( ( idx > -1) && ( idx < countTask)) { me = malloc(
sizeof( MSG_ENTRY) + len - 1); if( me == NULL) { lrc = -2; } else { me->len =
len; me->flags = flags; memcpy( me->data, buffer, len); aTask[idx]->msgcount++;
QuePut( &( aTask[idx]->queue), me); lrc = 0; } } OsUnlockMutex( tlMutex);
lua_pushnumber( L, lrc); return 1; } static int reg_tasklist(lua_State *L) {
long i; lua_newtable( L); for( i = 0; i < countTask; i++) if( aTask[i]->running)
{ lua_pushnumber( L, i + 1); lua_newtable( L); lua_pushstring( L, "script"); if(
aTask[i]->fname[0] == '=' ) lua_pushstring( L, "STRING_TASK"); else
lua_pushstring( L, aTask[i]->fname); lua_settable( L, -3); lua_pushstring( L,
"msgcount"); lua_pushnumber( L, aTask[i]->msgcount); lua_settable( L, -3); if(
aTask[i]->id != NULL) { lua_pushstring( L, "id"); lua_pushstring( L,
aTask[i]->id); lua_settable( L, -3); } lua_settable( L, -3); } return 1; }
static int reg_taskreceive(lua_State *L) { MSG_ENTRY *me; long lrc = -1; long i
= ( long) OsGetThreadData( threadDataKey); long tout = ( long)
luaL_optinteger(L, 1, INFINITE); if( i > -1) { #ifdef _WIN32 HANDLE qwh = (
HANDLE) GetQueNotEmptyHandle( &( aTask[i]->queue)); DWORD dwWait =
WaitForSingleObjectEx( qwh, tout, TRUE); if( ( aTask[i]->running == 1) && (
dwWait == WAIT_OBJECT_0)) { #else int psw; struct pollfd pfd; pfd.fd =
GetQueNotEmptyHandle( &( aTask[i]->queue)); pfd.events = POLLIN; psw = poll(
&pfd, 1, tout); if( ( aTask[i]->running == 1) && ( psw == 1)) { #endif _QueGet(
&( aTask[i]->queue), ( void **) &me); aTask[i]->msgcount--; lua_pushlstring( L,
me->data, me->len); lua_pushnumber( L, me->flags); free( me); lrc = 0; } else {
lua_pushnil( L); lua_pushnil( L); lrc = -2; } } else { lua_pushnil( L);
lua_pushnil( L); } lua_pushnumber( L, lrc); return 3; } static int reg_taskid(
lua_State *L) { long i = ( long) OsGetThreadData( threadDataKey);
lua_pushnumber( L, i + 1); return( 1); } static int reg_getqhandle( lua_State
*L) { long qwh = 0; long i = ( long) OsGetThreadData( threadDataKey); if( i >
-1) { qwh = GetQueNotEmptyHandle( &( aTask[i]->queue)); } lua_pushnumber( L, (
long) qwh); return( 1); } static int reg_cancel( lua_State *L) { long running;
long lrc = -1; long i = ( long) luaL_checknumber(L, 1); OsLockMutex( tlMutex,
INFINITE); if( ( i > 1) && ( i <= countTask)) if( --i != ( long)
OsGetThreadData( threadDataKey)) { lrc = 0; running = aTask[i]->running; if(
running) { aTask[i]->running = 2; lrc = OsCancelThread( aTask[i]->th); if(
aTask[i]->running == 2) aTask[i]->running = 0; } } OsUnlockMutex( tlMutex);
lua_pushnumber( L, lrc); return( 1); } static int reg_isrunning( lua_State *L) {
long running = 0; long i = ( long) luaL_checknumber(L, 1); OsLockMutex( tlMutex,
INFINITE); if( ( i > 1) && ( i <= countTask)) running = aTask[--i]->running ? 1
: 0; OsUnlockMutex( tlMutex); lua_pushboolean( L, running); return( 1); } /*
Module exported function */ static const struct luaL_reg lt_lib[] = { {
"create", reg_taskcreate}, { "register", reg_taskregister}, { "find",
reg_taskfind}, { "receive", reg_taskreceive}, { "post", reg_taskpost}, {
"unregister", reg_taskunregister}, { "list", reg_tasklist}, { "id", reg_taskid},
{ "getqhandle", reg_getqhandle}, { "cancel", reg_cancel}, { "isrunning",
reg_isrunning}, { NULL, NULL} }; LUATASK_API int luaopen_task(lua_State *L) {
int_tasklibinit(L); luaL_openlib (L, LT_NAMESPACE, lt_lib, 0); lua_pop (L, 1);
return 0; } static OS_THREAD_FUNC taskthread( void *vp) { TASK_ENTRY *te; int
status = 0; #if (_MSC_VER >= 1400) size_t l_init; char *init;
_dupenv_s(&init,&l_init,"LUA_INIT"); #else const char *init =
getenv("LUA_INIT"); #endif OsSetThreadData( threadDataKey, vp); OsLockMutex(
tlMutex, INFINITE); //te = aTask + ( ( long) vp); te = aTask[(long) vp]; #ifndef
NATV_WIN32 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_cleanup_push( taskCleanup, te); #endif lua_gc(te->L, LUA_GCSTOP, 0); /*
stop collector during initialization */ luaL_openlibs(te->L); /* open libraries
*/ luaopen_task(te->L); lua_gc(te->L, LUA_GCRESTART, 0); if( LRT_LIB_OVERRIDE !=
NULL) LRT_LIB_OVERRIDE( te->L); OsUnlockMutex( tlMutex); if (init != NULL) { if
(init[0] == '@') status = dofile( te->L, init+1); else status = dostring( te->L,
init, "=LUA_INIT"); #if (_MSC_VER >= 1400) free(init); #endif } if (status == 0)
{ if( te->fname[0] == '=' ) dostring( te->L, te->fname + 1, "=STRING_TASK");
else { if( LRT_DOFILE_OVERRIDE != NULL) LRT_DOFILE_OVERRIDE( te->L, te->fname);
else dofile( te->L, te->fname); } } OsLockMutex( tlMutex, INFINITE); #ifndef
NATV_WIN32 pthread_cleanup_pop( 0); #endif taskCleanup( te); OsUnlockMutex(
tlMutex); return( 0); }