//----------------------------------------------------------------------------- // // Copyright (C) 2015-2017 David Hill // // See COPYING for license information. // //----------------------------------------------------------------------------- // // Thread classes. // //----------------------------------------------------------------------------- #include "Thread.hpp" #include "Array.hpp" #include "BinaryIO.hpp" #include "Environment.hpp" #include "Module.hpp" #include "Scope.hpp" #include "Script.hpp" #include "Serial.hpp" #include //----------------------------------------------------------------------------| // Extern Functions | // namespace ACSVM { // // Thread constructor // Thread::Thread(Environment *env_) : env{env_}, link{this}, codePtr {nullptr}, module {nullptr}, scopeGbl{nullptr}, scopeHub{nullptr}, scopeMap{nullptr}, scopeMod{nullptr}, script {nullptr}, delay {0}, result {0} { } // // Thread destructor // Thread::~Thread() { } // // Thread::getInfo // ThreadInfo const *Thread::getInfo() const { return nullptr; } // // Thread::loadState // void Thread::loadState(Serial &in) { std::size_t count, countFull; in.readSign(Signature::Thread); module = env->getModule(env->readModuleName(in)); codePtr = &module->codeV[ReadVLN(in)]; scopeGbl = env->getGlobalScope(ReadVLN(in)); scopeHub = scopeGbl->getHubScope(ReadVLN(in)); scopeMap = scopeHub->getMapScope(ReadVLN(in)); scopeMod = scopeMap->getModuleScope(module); script = env->readScript(in); delay = ReadVLN(in); result = ReadVLN(in); count = ReadVLN(in); callStk.clear(); callStk.reserve(count + CallStkSize); while(count--) callStk.push(readCallFrame(in)); count = ReadVLN(in); dataStk.clear(); dataStk.reserve(count + DataStkSize); while(count--) dataStk.push(ReadVLN(in)); countFull = ReadVLN(in); count = ReadVLN(in); localArr.allocLoad(countFull, count); for(auto itr = localArr.beginFull(), end = localArr.end(); itr != end; ++itr) itr->loadState(in); countFull = ReadVLN(in); count = ReadVLN(in); localReg.allocLoad(countFull, count); for(auto itr = localReg.beginFull(), end = localReg.end(); itr != end; ++itr) *itr = ReadVLN(in); countFull = ReadVLN(in); count = ReadVLN(in); in.in->read(printBuf.getLoadBuf(countFull, count), countFull); state.state = static_cast(ReadVLN(in)); state.data = ReadVLN(in); state.type = ReadVLN(in); in.readSign(~Signature::Thread); } // // Thread::lockStrings // void Thread::lockStrings() const { for(auto &data : dataStk) ++env->getString(data)->lock; for(auto arr = localArr.beginFull(), end = localArr.end(); arr != end; ++arr) arr->lockStrings(env); for(auto reg = localReg.beginFull(), end = localReg.end(); reg != end; ++reg) ++env->getString(*reg)->lock; if(state == ThreadState::WaitScrS) ++env->getString(state.data)->lock; } // // Thread::readCallFrame // CallFrame Thread::readCallFrame(Serial &in) const { CallFrame out; out.module = env->getModule(env->readModuleName(in)); out.scopeMod = scopeMap->getModuleScope(out.module); out.codePtr = &out.module->codeV[ReadVLN(in)]; out.locArrC = ReadVLN(in); out.locRegC = ReadVLN(in); return out; } // // Thread::refStrings // void Thread::refStrings() const { for(auto &data : dataStk) env->getString(data)->ref = true; for(auto arr = localArr.beginFull(), end = localArr.end(); arr != end; ++arr) arr->refStrings(env); for(auto reg = localReg.beginFull(), end = localReg.end(); reg != end; ++reg) env->getString(*reg)->ref = true; if(state == ThreadState::WaitScrS) env->getString(state.data)->ref = true; } // // Thread::saveState // void Thread::saveState(Serial &out) const { out.writeSign(Signature::Thread); env->writeModuleName(out, module->name); WriteVLN(out, codePtr - module->codeV.data()); WriteVLN(out, scopeGbl->id); WriteVLN(out, scopeHub->id); WriteVLN(out, scopeMap->id); env->writeScript(out, script); WriteVLN(out, delay); WriteVLN(out, result); WriteVLN(out, callStk.size()); for(auto &call : callStk) writeCallFrame(out, call); WriteVLN(out, dataStk.size()); for(auto &data : dataStk) WriteVLN(out, data); WriteVLN(out, localArr.sizeFull()); WriteVLN(out, localArr.size()); for(auto itr = localArr.beginFull(), end = localArr.end(); itr != end; ++itr) itr->saveState(out); WriteVLN(out, localReg.sizeFull()); WriteVLN(out, localReg.size()); for(auto itr = localReg.beginFull(), end = localReg.end(); itr != end; ++itr) WriteVLN(out, *itr); WriteVLN(out, printBuf.sizeFull()); WriteVLN(out, printBuf.size()); out.out->write(printBuf.dataFull(), printBuf.sizeFull()); WriteVLN(out, state.state); WriteVLN(out, state.data); WriteVLN(out, state.type); out.writeSign(~Signature::Thread); } // // Thread::start // void Thread::start(Script *script_, MapScope *map, ThreadInfo const *, Word const *argV, Word argC) { link.insert(&map->threadActive); script = script_; module = script->module; codePtr = &module->codeV[script->codeIdx]; scopeMod = map->getModuleScope(module); scopeMap = map; scopeHub = scopeMap->hub; scopeGbl = scopeHub->global; callStk.reserve(CallStkSize); dataStk.reserve(DataStkSize); localArr.alloc(script->locArrC); localReg.alloc(script->locRegC); std::copy(argV, argV + std::min(argC, script->argC), &localReg[0]); delay = 0; result = 0; state = ThreadState::Running; } // // Thread::stop // void Thread::stop() { // Release execution resources. callStk.clear(); dataStk.clear(); localArr.clear(); localReg.clear(); printBuf.clear(); // Set state. state = ThreadState::Inactive; } // // Thread::unlockStrings // void Thread::unlockStrings() const { for(auto &data : dataStk) --env->getString(data)->lock; for(auto arr = localArr.beginFull(), end = localArr.end(); arr != end; ++arr) arr->unlockStrings(env); for(auto reg = localReg.beginFull(), end = localReg.end(); reg != end; ++reg) --env->getString(*reg)->lock; if(state == ThreadState::WaitScrS) --env->getString(state.data)->lock; } // // Thread::writeCallFrame // void Thread::writeCallFrame(Serial &out, CallFrame const &in) const { env->writeModuleName(out, in.module->name); WriteVLN(out, in.codePtr - in.module->codeV.data()); WriteVLN(out, in.locArrC); WriteVLN(out, in.locRegC); } } // EOF