BWAPI
SPAR/AIModule/SparAIModule/Utils/Component.h
Go to the documentation of this file.
00001 #pragma once
00002 #ifdef _DEBUG_COMPONENT
00003   #include "Logger.h"
00004   #include "EventHandler.h"
00005   #include "Event.h"
00006   #include "Task.h"
00007   #include <set>
00008   #include <BWAPI.h>
00009 #endif
00010 
00016 class Component
00017 {
00018 public:
00019   Component() {}
00020 
00021 #ifndef _DEBUG_COMPONENT
00022 
00023   virtual ~Component() {}
00024 
00025 #else
00026 
00027   Component(const Component&)
00028     : m_pendingSubscriptions()
00029     , m_pendingTasks()
00030   {}
00031 
00035   struct Subscription
00036   {
00037     Subscription(const EventHandlerBase* eventHandler, EventBase* ev)
00038       : m_eventHandler(eventHandler)
00039       , m_event(ev)
00040       , m_eventHandlerTypeInfo(typeid(*eventHandler))
00041       , m_eventTypeInfo(typeid(*ev))
00042     {}
00043     const EventHandlerBase* m_eventHandler;
00044     EventBase* m_event;
00045     const type_info& m_eventHandlerTypeInfo;
00046     const type_info& m_eventTypeInfo;
00047 
00048     friend bool operator< (const Subscription& subscription1, const Subscription& subscription2)
00049     {
00050       if (subscription1.m_eventHandler < subscription2.m_eventHandler)
00051         return true;
00052       else if (subscription1.m_eventHandler == subscription2.m_eventHandler)
00053         return subscription1.m_event < subscription2.m_event;
00054       else 
00055         return false;
00056     }
00057   };
00058 
00062   struct Task
00063   {
00064     Task(const RunnableTask* task)
00065       : m_task(task)
00066       //, m_taskTypeName(typeid(*task).name())
00067     {}
00068     const RunnableTask* const m_task;
00069     //const char* const m_taskTypeName;
00070 
00071     friend bool operator< (const Task& task1, const Task& task2)
00072     {
00073       return task1.m_task < task2.m_task;
00074     }
00075   };
00076 
00081   virtual ~Component()
00082   {
00083     verifyPendingSubscriptions("ERROR Component::~Component(): Make sure to unsubscribe EventHandler \"%s\" from event \"%s\" before its owner is deleted.");
00084     verifyPendingTasks("ERROR Component::~Component(): Make sure to deactivate task \"%s\" before its owner is deleted.");
00085 
00086     for (std::multiset<Subscription>::const_iterator it = m_pendingSubscriptions.begin(); it != m_pendingSubscriptions.end(); ++it)
00087     {
00088       it->m_event->onOwnerDeleted(this);
00089     }
00090   }
00094   void verifyPendingSubscriptions(const char* error) const
00095   {
00096     for (std::multiset<Subscription>::const_iterator it = m_pendingSubscriptions.begin(); it != m_pendingSubscriptions.end(); ++it)
00097     {
00098       SPAR_LOG(LogTypes::GENERAL_ERROR, error, 
00099         it->m_eventHandlerTypeInfo.name(), it->m_eventTypeInfo.name());
00100     }
00101   }
00105   void verifyPendingTasks(const char* error) const
00106   {
00107     for (std::set<Task>::const_iterator it = m_pendingTasks.begin(); it != m_pendingTasks.end(); ++it)
00108     {
00109       SPAR_LOG(LogTypes::GENERAL_ERROR, error, 
00110         typeid(*it->m_task).name());
00111     }
00112     // Does not work since tasks are removed from the owner upon destruction but stay in the scheduler
00113     // (this was done to keep the same behavior in both debug and release).
00114     //if (m_pendingTasks.empty())
00115     //{
00116     //  assert(!ownsAtLeastOneActiveTask());
00117     //}
00118   }
00124   void onEventSubscribe(const EventHandlerBase* eventHandler, EventBase* ev) const
00125   {
00126     m_pendingSubscriptions.insert(Subscription(eventHandler, ev));
00127   }
00133   void onEventUnsubscribe(const EventHandlerBase* eventHandler, EventBase* ev) const
00134   {
00135     std::multiset<Subscription>::iterator it = m_pendingSubscriptions.find(Subscription(eventHandler, ev));
00136     if (it == m_pendingSubscriptions.end())
00137     {
00138       SPAR_LOG(LogTypes::GENERAL_ERROR, "ERROR Component::onEventUnsubscribe(): EventHandler \"%\" has not yet subscribed to event \"%s\"", 
00139         typeid(*eventHandler).name(), typeid(*ev).name());
00140     }
00141     else
00142     {
00143       m_pendingSubscriptions.erase(it);
00144     }
00145   }
00152   void onEventDeleted(const EventHandlerBase* eventHandler, EventBase* ev) const
00153   {
00154     m_pendingSubscriptions.erase(Subscription(eventHandler, ev));
00155   }
00160   void onActivateTask(const RunnableTask* task) const
00161   {
00162     std::pair<std::set<Task>::iterator, bool> it = m_pendingTasks.insert(Task(task));
00163     if (!it.second)
00164     {
00165       SPAR_LOG(LogTypes::GENERAL_ERROR, "ERROR Component::onActivateTask(): Task \"%s\" has already been activated", 
00166         typeid(*task).name());
00167     }
00168   }
00173   void onDeactivateTask(const RunnableTask* task) const
00174   {
00175     size_t n = m_pendingTasks.erase(Task(task));
00176     if (n == 0)
00177     {
00178       SPAR_LOG(LogTypes::GENERAL_ERROR, "ERROR Component::onDeactivateTask(): Task \"%s\" has not yet been activated", 
00179         typeid(*task).name());
00180     }
00181   }
00182 
00183   void onDeleteTask(const RunnableTask* task) const
00184   {
00185     m_pendingTasks.erase(Task(task));
00186   }
00187 
00188 protected:
00189   bool ownsAtLeastOneActiveTask() const;
00190 
00195   mutable std::multiset<Subscription> m_pendingSubscriptions;
00200   mutable std::set<Task> m_pendingTasks;
00201 #endif
00202 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines