| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711 |
- /*
- ** Rings: Multiple Lua States
- ** $Id: rings.c,v 1.24 2008/06/30 17:52:31 carregal Exp $
- ** See Copyright Notice in license.html
- */
- #include <string.h>
- #include <stdio.h>
- #include "squirrel.h"
- #include <sqstdblob.h>
- #include <sqstdsystem.h>
- #include <sqstdio.h>
- #include <sqstdmath.h>
- #include <sqstdstring.h>
- #ifdef SLAVE_VM_WITH_OS_THREADS
- #include "mongoose.h"
- #endif // SLAVE_VM_WITH_OS_THREADS
- /*
- ** Copies values from State src to State dst.
- */
- static SQRESULT copy_values_between_vms (HSQUIRRELVM dst, HSQUIRRELVM src, int argc, int argIdx)
- {
- SQRESULT _rc_;
- sq_reservestack(dst, argc + 20);
- argc += argIdx; //we will work with argc args starting at argIdx
- for (; argIdx < argc; argIdx++)
- {
- switch (sq_gettype(src, argIdx))
- {
- case OT_INTEGER:
- SQ_GET_INTEGER(src, argIdx, vint);
- sq_pushinteger(dst, vint);
- break;
- case OT_FLOAT:
- SQ_GET_FLOAT(src, argIdx, vfloat);
- sq_pushfloat (dst, vfloat);
- break;
- case OT_BOOL:
- SQ_GET_BOOL(src, argIdx, vbool);
- sq_pushbool (dst, vbool);
- break;
- case OT_STRING:
- {
- SQ_GET_STRING(src, argIdx, vstr)
- sq_pushstring (dst, vstr, vstr_size);
- }
- break;
- case OT_ARRAY:
- {
- SQInteger size = sq_getsize(src, argIdx);
- sq_newarray(dst, size);
- for(SQInteger i=0; i<size; ++i)
- {
- sq_pushinteger(src, i);
- sq_get(src, -2);
- sq_pushinteger(dst, i);
- if(copy_values_between_vms(dst, src, 1, sq_gettop(src)) != SQ_OK) return SQ_ERROR;
- sq_poptop(src);
- sq_set(dst, -3);
- }
- }
- break;
- case OT_TABLE:
- {
- sq_newtable(dst);
- sq_pushnull(src);
- while(sq_next(src, -2) == SQ_OK)
- {
- SQInteger src_top = sq_gettop(src);
- if(copy_values_between_vms(dst, src, 1, src_top-1) != SQ_OK
- || copy_values_between_vms(dst, src, 1, src_top) != SQ_OK) return SQ_ERROR;
- sq_newslot(dst, -3, SQFalse);
- sq_pop(src, 2);
- }
- sq_pop(src,1);
- }
- break;
- case OT_USERPOINTER:
- {
- SQUserPointer ptr;
- sq_getuserpointer(src, argIdx, &ptr);
- sq_pushuserpointer(dst, ptr);
- }
- break;
- case OT_NULL:
- sq_pushnull(dst);
- break;
- default:
- return SQ_ERROR;
- }
- }
- return SQ_OK;
- }
- struct SlaveVM_st {
- HSQUIRRELVM v;
- HSQUIRRELVM master_vm;
- #ifdef SLAVE_VM_WITH_OS_THREADS
- mg_thread_mutex_t mutex;
- mg_thread_cond_t cond_var;
- mg_thread_t thread_id;
- int slave_state, master_state;
- bool isRunningAsThread;
- #endif // SLAVE_VM_WITH_OS_THREADS
- };
- static const SQChar sq_slave_vm_TAG[] = _SC("SlaveVM");
- static SQRESULT get_slave_vm_instance(HSQUIRRELVM v, SQInteger idx, SlaveVM_st **svm_st)
- {
- if(sq_getinstanceup(v, idx, (SQUserPointer*)svm_st, (void*)sq_slave_vm_TAG) != SQ_OK) return SQ_ERROR;
- if(!*svm_st) return sq_throwerror(v, _SC("slave vm already closed"));
- return SQ_OK;
- }
- #define GET_sq_slave_vm_INSTANCE(v, idx) \
- SlaveVM_st *self=NULL; HSQUIRRELVM svm; \
- if(get_slave_vm_instance(v, idx, &self) != SQ_OK) return SQ_ERROR; \
- svm = self->v;
- static SQRESULT sq_slave_vm__tostring (HSQUIRRELVM v)
- {
- GET_sq_slave_vm_INSTANCE(v, 1);
- sq_pushfstring (v, _SC("Squirrel vm (%p)"), svm);
- return 1;
- }
- #ifdef SLAVE_VM_WITH_OS_THREADS
- static int releaseSlaveThread(SlaveVM_st *self)
- {
- if(self->isRunningAsThread)
- {
- mg_thread_cond_destroy(&self->cond_var);
- mg_thread_mutex_destroy(&self->mutex);
- }
- return 0;
- }
- #endif // SLAVE_VM_WITH_OS_THREADS
- static SQRESULT sq_slave_vm_release_hook(SQUserPointer p, SQInteger size, void */*ep*/)
- {
- SlaveVM_st *self = (SlaveVM_st*)p;
- if(self && self->v)
- {
- #ifdef SLAVE_VM_WITH_OS_THREADS
- releaseSlaveThread(self);
- #endif // SLAVE_VM_WITH_OS_THREADS
- sq_close(self->v);
- self->v = NULL;
- sq_free(self, sizeof(*self));
- }
- return 0;
- }
- #ifdef SLAVE_VM_WITH_OS_THREADS
- #define SQ_getforeignptr_slave(v) \
- SlaveVM_st *self = (SlaveVM_st*)sq_getforeignptr(v);\
- if(!self) return sq_throwerror(v, _SC("No slavevm foreignptr found"));
- static SQRESULT sq_vm_thread_lock(HSQUIRRELVM v)
- {
- SQ_getforeignptr_slave(v);
- sq_pushinteger(v, mg_thread_mutex_lock(&self->mutex));
- return 1;
- }
- /*
- static SQRESULT sq_vm_thread_unlock(HSQUIRRELVM v)
- {
- SQ_getforeignptr_slave(v);
- sq_pushinteger(v, mg_thread_mutex_unlock(&self->mutex));
- return 1;
- }
- */
- static SQRESULT sq_vm_thread_cond_wait(HSQUIRRELVM v)
- {
- SQ_getforeignptr_slave(v);
- sq_pushinteger(v, mg_thread_cond_wait(&self->cond_var, &self->mutex));
- return 1;
- }
- static SQRESULT sq_vm_thread_master_state(HSQUIRRELVM v)
- {
- SQ_getforeignptr_slave(v);
- sq_pushinteger(v, self->master_state);
- return 1;
- }
- static SQRESULT sq_vm_thread_slave_state(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- SQ_getforeignptr_slave(v);
- SQ_OPT_INTEGER(v, 2, state, 0);
- sq_pushinteger(v, self->slave_state);
- if(sq_gettop(v) > 1) self->slave_state = state;
- return 1;
- }
- #endif // SLAVE_VM_WITH_OS_THREADS
- /*
- ** Creates a new SQuirrel vm.
- */
- static SQRESULT sq_slave_vm_constructor (HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- SQ_OPT_INTEGER(v, 2, stack_size, 1024);
- SQ_OPT_BOOL(v, 3, with_libraries, false);
- SQ_OPT_BOOL(v, 4, run_as_thread, false);
- HSQUIRRELVM self = sq_open(stack_size);
- /* Initialize environment */
- sq_setprintfunc(self,sq_getprintfunc(v),sq_geterrorfunc(v));
- if(with_libraries)
- {
- /* load base libraries */
- sq_pushroottable(self);
- sqstd_register_bloblib(self);
- sqstd_register_iolib(self);
- sqstd_register_systemlib(self);
- sqstd_register_mathlib(self);
- sqstd_register_stringlib(self);
- sq_poptop(self); //remove root table
- }
- SlaveVM_st *svm_st = (SlaveVM_st *)sq_malloc(sizeof(SlaveVM_st));
- memset(svm_st, 0, sizeof(*svm_st));
- #ifdef SLAVE_VM_WITH_OS_THREADS
- sq_setforeignptr(self, svm_st);
- if(run_as_thread)
- {
- svm_st->isRunningAsThread = true;
- svm_st->master_vm = v;
- mg_thread_mutex_init(&svm_st->mutex, NULL);
- mg_thread_cond_init(&svm_st->cond_var, NULL);
- sq_pushroottable(self);
- //sq_insertfunc(self, _SC("slavevm_thread_lock"), sq_vm_thread_lock, 1, _SC("."), SQFalse);
- //sq_insertfunc(self, _SC("slavevm_unlock"), sq_vm_thread_unlock, 1, _SC("."), SQFalse);
- sq_insertfunc(self, _SC("slavevm_thread_cond_wait"), sq_vm_thread_cond_wait, 1, _SC("."), SQFalse);
- sq_insertfunc(self, _SC("slavevm_thread_master_state"), sq_vm_thread_master_state, 1, _SC("."), SQFalse);
- sq_insertfunc(self, _SC("slavevm_thread_slave_state"), sq_vm_thread_slave_state, -1, _SC(".i"), SQFalse);
- sq_poptop(self); //remove root table
- }
- #endif // SLAVE_VM_WITH_OS_THREADS
- svm_st->v = self;
- svm_st->master_vm = v;
- sq_setinstanceup(v, 1, svm_st);
- sq_setreleasehook(v, 1, sq_slave_vm_release_hook);
- return 1;
- }
- static SQRESULT sq_slave_vm_preload_lib (HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- GET_sq_slave_vm_INSTANCE(v, 1);
- SQ_GET_STRING(v, 2, module_name);
- SQFUNCTION sq_func = sq_get_preload_module_func(v, module_name);
- SQBool rc = sq_func != NULL;
- if(rc)
- {
- sq_pushroottable(svm);
- sq_func(svm);
- sq_poptop(svm); //remove root table
- }
- sq_pushbool(v, rc);
- return 1;
- }
- #ifdef SLAVE_VM_WITH_OS_THREADS
- static SQRESULT checkTryLock(HSQUIRRELVM v, SlaveVM_st *self)
- {
- if(self->isRunningAsThread && mg_thread_mutex_trylock(&self->mutex))
- {
- return sq_throwerror(v, _SC("Could not aquire slave lock"));
- }
- return SQ_OK;
- }
- #endif // SLAVE_VM_WITH_OS_THREADS
- static SQRESULT sq_slave_vm_close(HSQUIRRELVM v)
- {
- GET_sq_slave_vm_INSTANCE(v, 1);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(checkTryLock(v, self)) return SQ_ERROR;
- releaseSlaveThread(self);
- #endif // SLAVE_VM_WITH_OS_THREADS
- sq_close(svm);
- sq_setinstanceup(v, 1, 0); //next calls will fail with "vm is closed"
- return 0;
- }
- static SQRESULT sq_slave_vm_call(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS_NO_TOP(v);
- GET_sq_slave_vm_INSTANCE(v, 1);
- SQ_GET_BOOL(v, 2, has_ret_val);
- SQ_GET_STRING(v, 3, func_name);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(checkTryLock(v, self)) return SQ_ERROR;
- #endif // SLAVE_VM_WITH_OS_THREADS
- SQInteger top = sq_gettop(svm);
- SQRESULT result = SQ_ERROR;
- sq_pushroottable(svm);
- sq_pushstring(svm, func_name, func_name_size);
- if(sq_get(svm, -2) == SQ_OK)
- {
- switch(sq_gettype(svm, -1))
- {
- case OT_CLOSURE:
- case OT_NATIVECLOSURE:
- case OT_CLASS:
- {
- sq_pushroottable(svm);
- int argc = sq_gettop(v) - 3;
- if(argc && copy_values_between_vms(svm, v, argc, 4) != SQ_OK)
- {
- result = sq_throwerror(v, sq_getlasterror_str(svm));
- goto cleanup;
- }
- if(sq_call(svm, argc+1, has_ret_val, SQFalse) != SQ_OK)
- {
- result = sq_throwerror(v, sq_getlasterror_str(svm));
- goto cleanup;
- }
- if(has_ret_val)
- {
- if(copy_values_between_vms(v, svm, 1, sq_gettop(svm)) == SQ_OK) result = 1;
- }
- else result = SQ_OK;
- }
- }
- }
- else
- {
- result = sq_throwerror(v, sq_getlasterror_str(svm));
- }
- cleanup:
- sq_settop(svm, top);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(self->isRunningAsThread) mg_thread_mutex_unlock(&self->mutex);
- #endif // SLAVE_VM_WITH_OS_THREADS
- return result;
- }
- static SQRESULT sq_slave_vm_set(HSQUIRRELVM v)
- {
- GET_sq_slave_vm_INSTANCE(v, 1);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(checkTryLock(v, self)) return SQ_ERROR;
- #endif // SLAVE_VM_WITH_OS_THREADS
- SQInteger top = sq_gettop(svm);
- SQRESULT result;
- sq_pushroottable(svm);
- if(copy_values_between_vms(svm, v, 1, 2) == SQ_OK
- && copy_values_between_vms(svm, v, 1, 3) == SQ_OK)
- {
- result = sq_newslot(svm, -3, SQFalse);
- if(result == SQ_ERROR) sq_throwerror(v, sq_getlasterror_str(svm));
- }
- else result = SQ_ERROR;
- sq_settop(svm, top);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(self->isRunningAsThread) mg_thread_mutex_unlock(&self->mutex);
- #endif // SLAVE_VM_WITH_OS_THREADS
- return result;
- }
- static SQRESULT sq_slave_vm_get(HSQUIRRELVM v)
- {
- GET_sq_slave_vm_INSTANCE(v, 1);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(checkTryLock(v, self)) return SQ_ERROR;
- #endif // SLAVE_VM_WITH_OS_THREADS
- SQInteger top = sq_gettop(svm);
- SQRESULT result = SQ_ERROR;
- sq_pushroottable(svm);
- if(copy_values_between_vms(svm, v, 1, 2) == SQ_OK)
- {
- if(sq_get(svm, -2) == SQ_OK
- && copy_values_between_vms(v, svm, 1, sq_gettop(svm)) == SQ_OK)
- {
- result = 1;
- }
- else
- {
- if(sq_gettop(v) == 3) result = 1; //we have a default value
- else sq_throwerror(v, sq_getlasterror_str(svm));
- }
- }
- sq_settop(svm, top);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(self->isRunningAsThread) mg_thread_mutex_unlock(&self->mutex);
- #endif // SLAVE_VM_WITH_OS_THREADS
- return result;
- }
- static SQRESULT sq_slave_vm_dofile(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- GET_sq_slave_vm_INSTANCE(v, 1);
- SQ_GET_STRING(v, 2, file_name);
- SQ_OPT_BOOL(v, 3, retval, false);
- SQ_OPT_BOOL(v, 4, printerror, false);
- SQ_OPT_BOOL(v, 5, show_warnings, false);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(checkTryLock(v, self)) return SQ_ERROR;
- #endif // SLAVE_VM_WITH_OS_THREADS
- SQInteger top = sq_gettop(svm);
- SQRESULT result = SQ_ERROR;
- sq_pushroottable(svm); //important always push the root table, because sqstd_dofile will try to do a sq_push(v, -2)
- if(sqstd_dofile(svm, file_name, retval, printerror, show_warnings) >= 0)
- {
- if(retval)
- {
- if(copy_values_between_vms(v, svm, 1, sq_gettop(svm)) == SQ_OK) result = 1;
- }
- else result = SQ_OK;
- }
- else sq_throwerror(v, sq_getlasterror_str(svm));
- sq_settop(svm, top);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(self->isRunningAsThread) mg_thread_mutex_unlock(&self->mutex);
- #endif // SLAVE_VM_WITH_OS_THREADS
- return result;
- }
- static SQRESULT sq_slave_vm_loadfile(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- GET_sq_slave_vm_INSTANCE(v, 1);
- SQ_GET_STRING(v, 2, func_name);
- SQ_GET_STRING(v, 3, file_name);
- SQ_OPT_BOOL(v, 4, printerror, false);
- SQ_OPT_BOOL(v, 5, show_warnings, false);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(checkTryLock(v, self)) return SQ_ERROR;
- #endif // SLAVE_VM_WITH_OS_THREADS
- SQInteger top = sq_gettop(svm);
- SQRESULT result = SQ_ERROR;
- sq_pushroottable(svm);
- sq_pushstring(svm, func_name, func_name_size);
- if(sqstd_loadfile(svm, file_name, printerror, show_warnings) >= 0)
- {
- result = sq_newslot(svm, -3, SQFalse);
- }
- sq_settop(svm, top);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(self->isRunningAsThread) mg_thread_mutex_unlock(&self->mutex);
- #endif // SLAVE_VM_WITH_OS_THREADS
- return result;
- }
- static SQRESULT sq_slave_vm_compilestring(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- GET_sq_slave_vm_INSTANCE(v, 1);
- SQ_GET_STRING(v, 2, func_name);
- SQ_GET_STRING(v, 3, str_script);
- SQ_OPT_BOOL(v, 4, printerror, false);
- SQ_OPT_BOOL(v, 5, show_warnings, false);
- SQ_OPT_INTEGER(v, 6, max_nested_includes, 0);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(checkTryLock(v, self)) return SQ_ERROR;
- #endif // SLAVE_VM_WITH_OS_THREADS
- SQInteger top = sq_gettop(svm);
- SQRESULT result = SQ_ERROR;
- sq_pushroottable(svm);
- sq_pushstring(svm, func_name, func_name_size);
- if(sq_compilebuffer(svm, str_script, str_script_size, func_name, printerror, show_warnings, max_nested_includes) >= 0)
- {
- result = sq_newslot(svm, -3, SQFalse);
- }
- else
- {
- const SQChar *last_error = sq_getlasterror_str(svm);
- if(last_error) {
- SQInteger line, column;
- sq_getlasterror_line_col(svm, &line, &column);
- result = sq_throwerror(v, _SC("compilestring %s %d:%d: %s"), func_name, line, column, last_error);
- }
- }
- sq_settop(svm, top);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(self->isRunningAsThread) mg_thread_mutex_unlock(&self->mutex);
- #endif // SLAVE_VM_WITH_OS_THREADS
- return result;
- }
- extern SQInteger _g_io_dostring(HSQUIRRELVM v);
- static SQRESULT sq_slave_vm_dostring(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- GET_sq_slave_vm_INSTANCE(v, 1);
- SQ_GET_STRING(v, 2, str);
- SQ_OPT_BOOL(v, 3, retval, false);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(checkTryLock(v, self)) return SQ_ERROR;
- #endif // SLAVE_VM_WITH_OS_THREADS
- SQInteger top = sq_gettop(svm);
- sq_pushroottable(svm); //important always push the root table, because sqstd_dofile will try to do a sq_push(v, -2)
- sq_pushstring(svm, str, str_size);
- sq_pushbool(svm, retval);
- SQRESULT result = _g_io_dostring(svm);
- if(result == SQ_ERROR) sq_settop(svm, top);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- if(self->isRunningAsThread) mg_thread_mutex_unlock(&self->mutex);
- #endif // SLAVE_VM_WITH_OS_THREADS
- return result;
- }
- static SQRESULT sq_slave_vm_is_thread_idle(HSQUIRRELVM v)
- {
- #ifdef SLAVE_VM_WITH_OS_THREADS
- GET_sq_slave_vm_INSTANCE(v, 1);
- int rc = mg_thread_mutex_trylock(&self->mutex) == 0;
- if(rc) mg_thread_mutex_unlock(&self->mutex);
- sq_pushbool(v, rc);
- #else
- sq_pushbool(v, SQTrue);
- #endif
- return 1;
- }
- static SQRESULT sq_slave_vm_is_runing_as_thread(HSQUIRRELVM v)
- {
- #ifdef SLAVE_VM_WITH_OS_THREADS
- GET_sq_slave_vm_INSTANCE(v, 1);
- sq_pushbool(v, self->isRunningAsThread);
- #else
- sq_pushbool(v, SQFalse);
- #endif
- return 1;
- }
- #ifdef SLAVE_VM_WITH_OS_THREADS
- #define check_run_as_thread(v) \
- if(!self->isRunningAsThread) return sq_throwerror(v, _SC("Slave VM not running as thread"))
- static void *slaveThreadTask(void *p)
- {
- SlaveVM_st *self = (SlaveVM_st*)p;
- self->thread_id = mg_thread_self();
- HSQUIRRELVM svm = self->v;
- int rc;
- SQInteger top, argc;
- rc = sq_getinteger(svm, -1, &top) == SQ_OK;
- if(rc)
- {
- rc = sq_getinteger(svm, -2, &argc) == SQ_OK;
- if(rc)
- {
- sq_pop(svm, 2); //remove top & argc
- rc = sq_call(svm, argc+1, SQFalse, SQFalse);
- }
- sq_settop(svm, top);
- }
- rc = mg_thread_mutex_unlock(&self->mutex);
- self->thread_id = 0;
- //printf("%d:%d:%s\n", __LINE__, rc, __FILE__);
- return NULL;
- }
- extern void sq_system_sleep(int n);
- static SQRESULT sq_slave_vm_thread_run(HSQUIRRELVM v)
- {
- GET_sq_slave_vm_INSTANCE(v, 1);
- check_run_as_thread(v);
- int rc;
- const SQChar *func_name;
- SQInteger func_name_size;
- if(self->thread_id) return sq_throwerror(v, _SC("slavevm already running in a thread"));
- SQInteger top = sq_gettop(svm);
- rc = mg_thread_mutex_trylock(&self->mutex) == 0;
- if(rc)
- {
- sq_getstr_and_size(v, 2, &func_name, &func_name_size);
- sq_pushstring(svm, func_name, func_name_size);
- sq_getonroottable(svm);
- //printf("%d:%s\n", __LINE__, __FILE__);
- rc = (sq_gettype(svm, -1) == OT_CLOSURE);
- if( rc )
- {
- //printf("%d:%s\n", __LINE__, __FILE__);
- sq_pushroottable(svm);
- int argc = sq_gettop(v) - 2;
- rc = ( (argc == 0) || (copy_values_between_vms(svm, v, argc, 3) == SQ_OK));
- if(rc)
- {
- sq_pushinteger(svm, argc);
- sq_pushinteger(svm, top);
- rc = mg_start_thread(slaveThreadTask, self) == 0;
- if(rc) goto done;
- }
- //printf("%d:%d:%s\n", __LINE__, rc, __FILE__);
- }
- sq_settop(svm, top); //something went wrong reset slave stack
- }
- done:
- sq_pushbool(v, rc);
- return 1;
- }
- static SQRESULT sq_slave_vm_thread_trylock(HSQUIRRELVM v)
- {
- GET_sq_slave_vm_INSTANCE(v, 1);
- check_run_as_thread(v);
- sq_pushinteger(v, mg_thread_mutex_trylock(&self->mutex));
- return 1;
- }
- static SQRESULT sq_slave_vm_thread_unlock(HSQUIRRELVM v)
- {
- GET_sq_slave_vm_INSTANCE(v, 1);
- check_run_as_thread(v);
- sq_pushinteger(v, mg_thread_mutex_unlock(&self->mutex));
- return 1;
- }
- static SQRESULT sq_slave_vm_thread_cond_signal(HSQUIRRELVM v)
- {
- GET_sq_slave_vm_INSTANCE(v, 1);
- check_run_as_thread(v);
- sq_pushinteger(v, mg_thread_cond_signal(&self->cond_var));
- return 1;
- }
- static SQRESULT sq_slave_vm_thread_master_state(HSQUIRRELVM v)
- {
- SQ_FUNC_VARS(v);
- GET_sq_slave_vm_INSTANCE(v, 1);
- check_run_as_thread(v);
- SQ_OPT_INTEGER(v, 2, state, 0);
- sq_pushinteger(v, self->master_state);
- if(sq_gettop(v) > 1) self->master_state = state;
- return 1;
- }
- static SQRESULT sq_slave_vm_thread_slave_state(HSQUIRRELVM v)
- {
- GET_sq_slave_vm_INSTANCE(v, 1);
- check_run_as_thread(v);
- sq_pushinteger(v, self->slave_state);
- return 1;
- }
- #endif // SLAVE_VM_WITH_OS_THREADS
- #ifdef __cplusplus
- extern "C" {
- #endif
- SQRESULT sqext_register_sq_slave_vm(HSQUIRRELVM v)
- {
- const SQChar get_set_validation_mask[] = _SC("x s|n|p s|n|b|a|t|p|o");
- sq_pushstring(v,sq_slave_vm_TAG, -1);
- sq_newclass(v, SQFalse);
- sq_settypetag(v,-1,(void*)sq_slave_vm_TAG);
- sq_insertfunc(v, _SC("constructor"), sq_slave_vm_constructor, -1, _SC("xibb"), SQFalse);
- sq_insertfunc(v, _SC("_tostring"), sq_slave_vm__tostring, 1, _SC("x"), SQFalse);
- sq_insertfunc(v, _SC("close"), sq_slave_vm_close, 1, _SC("x"), SQFalse);
- sq_insertfunc(v, _SC("set"), sq_slave_vm_set, 3, get_set_validation_mask, SQFalse);
- sq_insertfunc(v, _SC("_set"), sq_slave_vm_set, 3, get_set_validation_mask, SQFalse);
- sq_insertfunc(v, _SC("get"), sq_slave_vm_get, -2, get_set_validation_mask, SQFalse);
- sq_insertfunc(v, _SC("_get"), sq_slave_vm_get, -2, get_set_validation_mask, SQFalse);
- sq_insertfunc(v, _SC("dofile"), sq_slave_vm_dofile, -2, _SC("xsbbb"), SQFalse);
- sq_insertfunc(v, _SC("loadfile"), sq_slave_vm_loadfile, -3, _SC("xssbb"), SQFalse);
- sq_insertfunc(v, _SC("dostring"), sq_slave_vm_dostring, -2, _SC("xsb"), SQFalse);
- sq_insertfunc(v, _SC("compilestring"), sq_slave_vm_compilestring, -3, _SC("xssbbi"), SQFalse);
- sq_insertfunc(v, _SC("call"), sq_slave_vm_call, -3, _SC("xbs"), SQFalse);
- sq_insertfunc(v, _SC("is_thread_idle"), sq_slave_vm_is_thread_idle, 1, _SC("x"), SQFalse);
- sq_insertfunc(v, _SC("is_runing_as_thread"), sq_slave_vm_is_runing_as_thread, 1, _SC("x"), SQFalse);
- #ifdef SLAVE_VM_WITH_OS_THREADS
- sq_insertfunc(v, _SC("thread_run"), sq_slave_vm_thread_run, -2, _SC("xs"), SQFalse);
- sq_insertfunc(v, _SC("thread_trylock"), sq_slave_vm_thread_trylock, 1, _SC("x"), SQFalse);
- sq_insertfunc(v, _SC("thread_unlock"), sq_slave_vm_thread_unlock, 1, _SC("x"), SQFalse);
- sq_insertfunc(v, _SC("thread_cond_signal"), sq_slave_vm_thread_cond_signal, 1, _SC("x"), SQFalse);
- sq_insertfunc(v, _SC("thread_master_state"), sq_slave_vm_thread_master_state, -1, _SC("xi"), SQFalse);
- sq_insertfunc(v, _SC("thread_slave_state"), sq_slave_vm_thread_slave_state, 1, _SC("x"), SQFalse);
- #endif // SLAVE_VM_WITH_OS_THREADS
- sq_insertfunc(v, _SC("preload_lib"), sq_slave_vm_preload_lib, 2, _SC("xs"), SQFalse);
- sq_newslot(v,-3,SQTrue); //push sq_slave_vm class
- return 0;
- }
- #ifdef __cplusplus
- }
- #endif
|