BWAPI
SPAR/AIModule/SparAIModule/Utils/Process.h
Go to the documentation of this file.
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 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines