lua-users home
lua-l archive

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


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); }