00001 00002 #include "virtualMachine.h" 00003 00004 00005 00006 virtualMachine::~virtualMachine() 00007 { 00008 // delete all processes 00009 std::vector<process*>::iterator pit = m_pProcesses.begin(); 00010 for( ; pit!=m_pProcesses.end();++pit) 00011 { 00012 if(*pit) delete (*pit); 00013 } 00014 } 00015 00016 00017 instruction virtualMachine::addInstruction(instructionPtr instrPtr) 00018 { 00019 push_back(instrPtr); 00020 return static_cast<instruction>(size()); 00021 } 00022 00023 00024 bool virtualMachine::replaceInstruction(instruction instr, instructionPtr instrPtr) 00025 { 00026 if(instr>=size()) 00027 { 00028 WARN("instruction does not exist"); 00029 return false; 00030 } 00031 00032 if(!instrPtr) 00033 { 00034 WARN("NULL pointer when replacing instruction"); 00035 return false; 00036 } 00037 00038 (*this)[instr] = instrPtr; 00039 00040 return true; 00041 } 00042 00043 00044 processId virtualMachine::run(program& prog) 00045 { 00046 if(size()==0) 00047 { 00048 WARN("cannot execute programs on virtual machine with no instruction set"); 00049 return 0; 00050 } 00051 00052 // get a process id 00053 uInt pid = m_processIdGen.getId(); 00054 if(pid) 00055 { 00056 // create the process 00057 if(pid>m_pProcesses.size()) 00058 { 00059 // new process 00060 process* pNewProc = new process(prog, pid); 00061 m_pProcesses.push_back(pNewProc); 00062 } else 00063 { 00064 // recycled process 00065 process* pNewProc = m_pProcesses[pid-1]; 00066 pNewProc->m_pProgram = &prog; 00067 pNewProc->spawnThread(0); 00068 } 00069 00070 m_numProcesses++; 00071 return pid; 00072 } 00073 00074 return 0; 00075 } 00076 00077 00078 void virtualMachine::kill(processId pid) 00079 { 00080 if( pid > 0 00081 && pid <= m_pProcesses.size() 00082 && !m_pProcesses[pid-1]->isTerminated() ) 00083 { 00084 kill(*(m_pProcesses[pid-1])); 00085 } 00086 } 00087 00088 00089 process* virtualMachine::getProcess(processId pid) 00090 { 00091 if( pid > 0 00092 && pid <= m_pProcesses.size() 00093 && !m_pProcesses[pid-1]->isTerminated() ) 00094 { 00095 return m_pProcesses[pid-1]; 00096 } 00097 00098 return NULL; 00099 } 00100 00101 00102 void virtualMachine::step() 00103 { 00104 m_activeProcesses = false; 00105 00106 // loop through all processes 00107 for( processId pid=0; pid<m_pProcesses.size(); ++pid) 00108 { 00109 process& proc = *(m_pProcesses[pid]); 00110 00111 // loop through each thread of the process 00112 for(threadId tid=0; tid<proc.size();++tid) 00113 { 00114 // check if the process can still be executed 00115 // (any thread could kill the process so we 00116 // need to check after each thread has been 00117 // updated) 00118 if(canBeExecuted(proc)) 00119 { 00120 m_activeProcesses = true; 00121 00122 thread& t = *(proc[tid]); 00123 00124 // check if the thread is executing 00125 if(!t.isTerminated()) 00126 { 00127 // execute the thread 00128 t%=static_cast<uInt>(proc.m_pProgram->size()); 00129 instruction instr = proc.m_pProgram->read<instruction>(t)%static_cast<uInt>(size()); 00130 (*this)[instr](*this,proc,t); 00131 } 00132 00133 } else if(shouldBeTerminated(proc)) 00134 { 00135 // if the process is not being executed 00136 // check if it should be terminated and 00137 // if so terminate it 00138 kill(proc); 00139 } 00140 } 00141 00142 } 00143 } 00144 00145 00146 void virtualMachine::setNumUsedCycles(float num) 00147 { 00148 m_usedCycles = num; 00149 if(m_usedCycles>1.0f) m_usedCycles = 1.0f; 00150 } 00151 00152 00153 void virtualMachine::update(float deltaT) 00154 { 00155 if(m_usedCycles<=0.0f) return; 00156 00157 if(m_idleCnt >= 1.0f/m_usedCycles) 00158 { 00159 step(); 00160 } else 00161 { 00162 m_idleCnt++; 00163 } 00164 } 00165 00166 00167 bool virtualMachine::canBeExecuted(process& proc) 00168 { 00169 return !proc.isTerminated(); 00170 } 00171 00172 00173 bool virtualMachine::shouldBeTerminated(process& proc) 00174 { 00175 return proc.m_id!=0; 00176 } 00177 00178 00179 void virtualMachine::kill(process& proc) 00180 { 00181 m_processIdGen.releaseId(proc.m_id); 00182 proc.clean(); 00183 m_numProcesses--; 00184 } 00185 00186