BWAPI
|
00001 #pragma once 00002 #include "Utils.h." 00003 #include "Component.h" 00004 #include "Event.h" 00005 #include "Logger.h" 00006 #include "SafeList.h" 00007 #include "SafeListAdaptor.h" 00008 #include <boost/iterator/transform_iterator.hpp> 00009 #include <cassert> 00010 #include <iostream> 00011 #include <algorithm> 00012 00017 class Process : public Component 00018 { 00019 protected: 00023 class Mode 00024 { 00025 public: 00026 virtual ~Mode() {} // Useless aside from allowing dynamic_casting of modes 00027 00028 friend bool operator== (const Mode& mode1, const Mode& mode2) { return &mode1 == &mode2; } 00029 friend bool operator!= (const Mode& mode1, const Mode& mode2) { return &mode1 != &mode2; } 00030 00031 protected: 00032 friend class Process; 00033 Mode() {} // Only possible (non-derived) mode is WaitingToExecute 00034 }; 00035 00039 class ExecutionMode : public Mode 00040 { 00041 }; 00042 00046 class TerminationMode : public Mode 00047 { 00048 }; 00049 private: 00050 struct ProcessWrapper; 00051 struct extract_process_const; 00052 00053 public: 00054 Process(const Process* parent) 00055 : m_currentMode(&WaitingToExecute) 00056 , m_parent(parent) 00057 , m_childProcessTerminatedEventHandler(*this) 00058 , m_zombifyOnTerminate(false) 00059 { 00060 } 00061 00062 ~Process() 00063 { 00064 assert(m_executingChildProcesses.empty()); 00065 } 00066 00071 static void zombifyOnTerminate(const Process* process) 00072 { 00073 process->m_zombifyOnTerminate = true; 00074 //ProcessZombification::zombifyOnTerminate(process); 00075 } 00076 00077 const Mode& getCurrentMode() const 00078 { 00079 return *m_currentMode; 00080 } 00081 00082 const ExecutionMode& getExecutionMode() const 00083 { 00084 assert(isExecuting()); 00085 return *dynamic_cast<const ExecutionMode*>(m_currentMode); 00086 } 00087 00088 const TerminationMode& getTerminationMode() const 00089 { 00090 assert(isTerminated()); 00091 return *dynamic_cast<const TerminationMode*>(m_currentMode); 00092 } 00093 00094 // Either "waiting to start", "running", or "terminated" (with several possible states when running or terminated) 00095 00096 bool isWaitingToExecute() const 00097 { 00098 return m_currentMode == &WaitingToExecute; 00099 } 00100 00101 bool isExecuting() const 00102 { 00103 return dynamic_cast<const ExecutionMode*>(m_currentMode) != NULL; 00104 } 00105 00106 bool isTerminated() const 00107 { 00108 return dynamic_cast<const TerminationMode*>(m_currentMode) != NULL; 00109 } 00110 00114 void execute() 00115 { 00116 assert(isWaitingToExecute()); 00117 00118 // Can't execute a process if parent has terminated (or has not yet started) 00119 if (m_parent == NULL || m_parent->isExecuting()) 00120 { 00121 m_currentMode = &Executing; 00122 00123 executeImpl(); 00124 00125 if (isExecuting() && m_parent != NULL) 00126 m_parent->onChildProcessExecuted(this); 00127 } 00128 } 00129 00133 void externalTerminate() 00134 { 00135 terminate(ExternalEvent); 00136 } 00137 00138 DECLARE_EVENT(OnTerminate); 00139 00140 #ifdef USE_SPAR_GUI 00141 DECLARE_EVENT1(OnChildProcessExecuted, const Process*); 00142 #endif 00143 00148 OnTerminate& getTerminateEvent() const { return m_terminateEvent; } 00149 00150 size_t getNbChildProcesses() const 00151 { 00152 return m_executingChildProcesses.size(); 00153 } 00154 00155 template <class Function> 00156 Function for_each_child_process(Function function) 00157 { 00158 struct FunctionTraits : std::unary_function<Process*, SafeListBase::FunctionReturn> 00159 { 00160 FunctionTraits(Function function) : m_function(function) 00161 {} 00162 SafeListBase::FunctionReturn operator()(Process* process) const 00163 { 00164 return m_function(process); 00165 } 00166 Function m_function; 00167 }; 00168 FunctionTraits functionTraits(function); 00169 composite_functor<FunctionTraits, extract_process> composite(functionTraits); 00170 composite_functor<FunctionTraits, extract_process> composite2 = m_executingChildProcesses.for_each<composite_functor<FunctionTraits, extract_process>>(composite); 00171 return composite2.m_f1.m_function; 00172 00173 //return m_executingChildProcesses.for_each(composite).m_f1.m_function; 00174 } 00175 00176 static const Mode WaitingToExecute; 00180 static const ExecutionMode Executing; 00184 static const TerminationMode Success; 00188 static const TerminationMode ExternalEvent; 00189 00190 struct TerminateProcess 00191 { 00192 typedef SafeListBase::FunctionReturn result_type; 00193 00194 SafeListBase::FunctionReturn operator()(Process* process) const 00195 { 00196 process->externalTerminate(); 00197 return SafeListBase::FunctionReturn(); 00198 } 00199 }; 00200 00201 friend std::ostream& operator<<(std::ostream& out, const Process& process) 00202 { 00203 process.output(out); 00204 return out; 00205 } 00206 00208 // GUI // 00210 typedef boost::transform_iterator<extract_process_const, ConstSafeListAdaptor<ProcessWrapper>::const_iterator> ProcessIterator; 00211 std::pair<ProcessIterator, ProcessIterator> getCurrentChildProcesses() const 00212 { 00213 ConstSafeListAdaptor<ProcessWrapper> adaptor(m_executingChildProcesses); 00214 return std::make_pair(ProcessIterator(adaptor.unsafe_begin()), ProcessIterator(adaptor.unsafe_end())); 00215 } 00216 virtual std::set<BWAPI::Unit*> getCommandedUnits() const = 0; 00217 00218 protected: 00219 virtual void output(std::ostream& out) const = 0; 00220 00221 void changeMode(const ExecutionMode& newMode) 00222 { 00223 assert(isExecuting()); 00224 00225 m_currentMode = &newMode; 00226 } 00227 00228 void terminate(const TerminationMode& mode); 00229 00230 virtual void executeImpl() {} 00231 00232 virtual void terminateImpl() {} 00233 00239 void onChildProcessExecuted(Process* process) const 00240 { 00241 // No duplicates 00242 assert(std::find(ConstSafeListAdaptor<ProcessWrapper>(m_executingChildProcesses).unsafe_begin(), 00243 ConstSafeListAdaptor<ProcessWrapper>(m_executingChildProcesses).unsafe_end(), 00244 ProcessWrapper(process)) == ConstSafeListAdaptor<ProcessWrapper>(m_executingChildProcesses).unsafe_end()); 00245 00246 SafeList<ProcessWrapper>::iterator pos = m_executingChildProcesses.add(ProcessWrapper(process)); 00247 ProcessWrapper& wrapper = *pos; 00248 wrapper.m_posInContainer = pos; 00249 Process::OnTerminate::SubscriberID sid = process->getTerminateEvent().subscribe(&m_childProcessTerminatedEventHandler, &wrapper); 00250 unused(sid); 00251 #ifdef _DEBUG_COMPONENT 00252 wrapper.m_processTerminationID = sid; 00253 #endif 00254 #ifdef USE_SPAR_GUI 00255 m_childProcessExecutedEvent.raise(process); 00256 #endif 00257 } 00258 00265 void onChildProcessTerminated(void* data) const 00266 { 00267 ProcessWrapper* wrapper = reinterpret_cast<ProcessWrapper*>(data); 00268 #ifdef _DEBUG_COMPONENT 00269 wrapper->m_process->getTerminateEvent().unsubscribe(wrapper->m_processTerminationID); 00270 #endif 00271 m_executingChildProcesses.erase(wrapper->m_posInContainer); 00272 } 00273 00274 private: 00275 //class ProcessZombification : public Component 00276 //{ 00277 //public: 00278 // static void zombifyOnTerminate(const Process* process) 00279 // { 00280 // process->getTerminateEvent().subscribe(&s_processZombification.m_zombifyProcessOnTerminateEventHandler, const_cast<void*>(reinterpret_cast<const void*>(process))); 00281 // } 00282 // void onTerminate(void* data); 00283 //private: 00284 // static ProcessZombification s_processZombification; 00285 // ProcessZombification() 00286 // : m_zombifyProcessOnTerminateEventHandler(*this) 00287 // {} 00288 // EVENT_HANDLER(ProcessZombification, onTerminate) m_zombifyProcessOnTerminateEventHandler; 00289 //}; 00290 00291 struct ProcessWrapper 00292 { 00293 ProcessWrapper(Process* process) 00294 : m_process(process) { } 00295 00296 bool operator==(const ProcessWrapper& other) const 00297 { 00298 return m_process == other.m_process; 00299 } 00300 00301 Process* const m_process; 00305 SafeList<ProcessWrapper>::iterator m_posInContainer; 00306 00307 #ifdef _DEBUG_COMPONENT 00308 00311 Process::OnTerminate::SubscriberID m_processTerminationID; 00312 #endif 00313 }; 00314 struct extract_process : std::unary_function<ProcessWrapper&,Process*> 00315 { 00316 Process* operator()(ProcessWrapper& wrapper) const { return wrapper.m_process; } 00317 }; 00318 struct extract_process_const : std::unary_function<const ProcessWrapper&,const Process*> 00319 { 00320 const Process* operator()(const ProcessWrapper& wrapper) const { return wrapper.m_process; } 00321 }; 00322 00326 const Process* const m_parent; 00327 00331 const Mode* m_currentMode; 00332 00336 EVENT(OnTerminate) m_terminateEvent; 00337 00338 00339 #ifdef USE_SPAR_GUI 00340 EVENT(OnChildProcessExecuted) m_childProcessExecutedEvent; 00341 #endif 00342 00346 mutable EVENT_HANDLER(Process, onChildProcessTerminated) m_childProcessTerminatedEventHandler; 00347 00351 mutable SafeList<ProcessWrapper> m_executingChildProcesses; 00352 00356 mutable bool m_zombifyOnTerminate; 00357 };