void TimeScheduler::update(float time) { while(!schedule.empty() && schedule.front().wakeup_time < time) { HSQOBJECT thread_ref = schedule.front().thread_ref; sq_pushobject(global_vm, thread_ref); sq_getweakrefval(global_vm, -1); HSQUIRRELVM scheduled_vm; if(sq_gettype(global_vm, -1) == OT_THREAD && SQ_SUCCEEDED(sq_getthread(global_vm, -1, &scheduled_vm))) { if(SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue, SQFalse))) { std::ostringstream msg; msg << "Error waking VM: "; sq_getlasterror(scheduled_vm); if(sq_gettype(scheduled_vm, -1) != OT_STRING) { msg << "(no info)"; } else { const char* lasterr; sq_getstring(scheduled_vm, -1, &lasterr); msg << lasterr; } log_warning << msg.str() << std::endl; sq_pop(scheduled_vm, 1); } } sq_release(global_vm, &thread_ref); sq_pop(global_vm, 2); std::pop_heap(schedule.begin(), schedule.end()); schedule.pop_back(); } }
static SQInteger thread_wakeup(HSQUIRRELVM v) { SQObjectPtr o = stack_get(v,1); if(type(o) == OT_THREAD) { SQVM *thread = _thread(o); SQInteger state = sq_getvmstate(thread); if(state != SQ_VMSTATE_SUSPENDED) { switch(state) { case SQ_VMSTATE_IDLE: return sq_throwerror(v,_SC("cannot wakeup a idle thread")); break; case SQ_VMSTATE_RUNNING: return sq_throwerror(v,_SC("cannot wakeup a running thread")); break; } } SQInteger wakeupret = sq_gettop(v)>1?1:0; if(wakeupret) { sq_move(thread,v,2); } if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1,SQFalse))) { sq_move(v,thread,-1); sq_pop(thread,1); if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) { sq_pop(thread,1); } return 1; } return SQ_ERROR; } return sq_throwerror(v,_SC("wrong parameter")); }
void ThreadQueue::wakeup() { // we traverse the list in reverse orders and use indices. This should be // robust for scripts that add new entries to the list while we're traversing // it size_t i = threads.size() - 1; size_t end = static_cast<size_t>(0 - 1); size_t size_begin = threads.size(); while(i != end) { HSQOBJECT object = threads[i]; sq_pushobject(global_vm, object); sq_getweakrefval(global_vm, -1); HSQUIRRELVM scheduled_vm; if(sq_gettype(global_vm, -1) == OT_THREAD && SQ_SUCCEEDED(sq_getthread(global_vm, -1, &scheduled_vm))) { if(SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue, SQFalse))) { log_warning << "Couldn't wakeup scheduled squirrel VM" << std::endl; } } sq_release(global_vm, &object); sq_pop(global_vm, 1); i--; } threads.erase(threads.begin(), threads.begin() + size_begin); }
static bool program_memoryarea(HSQUIRRELVM co, const struct reader_handle *h, struct flash_memory_driver *t, bool compare, SQInteger *state, struct textcontrol *log) { if(t->programming.length == 0){ if(t->programming.offset != 0 && compare == true){ if(program_compare(h, t) == false){ log->append(log->object, wgT("%s memory compare failed, offset 0x%06x\n"), t->memory.name, t->programming.offset); return false; } } sq_wakeupvm(co, SQFalse, SQFalse, SQTrue, SQFalse); *state = sq_getvmstate(co); }else{ program_execute(h, t); } return true; }
/** * スレッドのメイン処理 * @param diff 経過時間 * @return スレッド実行終了なら true */ bool Thread::_main(long diff) { // スレッドとして動作できてない場合は即終了 if (_status == THREAD_NONE) { return true; } if (_status == THREAD_LOADING_FILE) { // ファイル読み込み処理 const char *dataAddr; int dataSize; if (sqobjCheckFile(_fileHandler, &dataAddr, &dataSize)) { _init(); SQRESULT ret = sqstd_loadmemory(_thread, dataAddr, dataSize, _scriptName.getString(), SQTrue); sqobjCloseFile(_fileHandler); _fileHandler = NULL; if (SQ_SUCCEEDED(ret)) { _status = THREAD_RUN; } else { // exit相当 printError(); _exit(); return true; } } else { // 読み込み完了待ち return false; } } else if (_status == THREAD_LOADING_FUNC) { // スクリプト読み込み処理 _init(); _func.push(_thread); _func.clear(); _status = THREAD_RUN; } _currentTick += diff; // タイムアウト処理 if (_waitTimeout >= 0) { _waitTimeout -= diff; if (_waitTimeout < 0) { _clearWait(); } } // スレッド実行 if (!isWait() && _status == THREAD_RUN) { SQRESULT result; if (sq_getvmstate(_thread) == SQ_VMSTATE_SUSPENDED) { _waitResult.push(_thread); _waitResult.clear(); result = sq_wakeupvm(_thread, SQTrue, SQTrue, SQTrue, SQFalse); } else { sq_pushroottable(_thread); SQInteger n = _args.pushArray(_thread) + 1; _args.clear(); result = sq_call(_thread, n, SQTrue, SQTrue); } if (SQ_FAILED(result)) { // スレッドがエラー終了 printError(); _exit(); } else { // 終了コード取得。return/suspend の値が格納される _exitCode.getStack(_thread, -1); sq_pop(_thread, 1); if (sq_getvmstate(_thread) == SQ_VMSTATE_IDLE) { // スレッドが終了 _exit(); } } } return _status == THREAD_NONE; }