Remove dynamic exceptions
[anna.git] / include / anna / timex / Engine.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #ifndef anna_timex_Engine_hpp
10 #define anna_timex_Engine_hpp
11
12 #include <pthread.h>
13
14 #include <vector>
15 #include <map>
16
17 #include <anna/app/Component.hpp>
18
19 #include <anna/timex/TimeEvent.hpp>
20
21 namespace anna {
22
23 class Thread;
24
25 namespace timex {
26
27 class TickProducer;
28 class TickConsumer;
29
30 namespace st {
31 class TickProducer;
32 }
33
34 namespace mt {
35 class TickProducer;
36 }
37
38 /**
39    Controlador general de tiempos.
40
41    El siguiente ejemplo muestra como obtener la instancia del gestor de tiempo asociado a nuestra aplicacion:
42
43    \code
44
45    #include <anna.timex.Engine.h>
46
47    void cualquierFuncion (Timer* timer)
48       noexcept(false)
49    {
50       Engine* timeController = anna::component <Engine> (FILE_LOCATION);
51       timerController->activate (timer);
52    }
53
54    Si el componente Engine no hubiera sido registrado (instanciado) en nuestra aplicacion el metodo
55    template anna::component lanzara una excepcion.
56
57    \endcode
58
59    \see anna::Component
60 */
61
62 class Engine : public app::Component {
63 public:
64   /**
65      Resolucion minima (en milisegundos) soportada por el controlador de tiempos.
66   */
67   static const Millisecond minResolution;
68
69   /**
70      Constructor.
71
72      Asocia automatica el objeto controlador de tiempo a la instancia de nuestra aplicacin.
73
74      @param maxTimeout maxima duracion de los eventos de tiempo que vamos a establecer.
75      @param resolution Resolucion ofrecida para este controlador de tiempos. La duracion minima
76      de un evento de tiempo de ser igual o mayor a este parametro.
77   */
78   Engine(const Millisecond & maxTimeout, const Millisecond & resolution);
79
80   /**
81      Destructor
82   */
83   virtual ~Engine();
84
85   /**
86      Devuelve la resolucion del controlador de tiempo indicada en el contructor.
87      \return la resolucion del controlador de tiempo indicada en el contructor.
88   */
89   const Millisecond & getResolution() const { return a_resolution; }
90
91   /**
92      Devuelve el periodo máximo de temporización indicado en el constructor.
93      \return el periodo máximo de temporización indicado en el constructor.
94   */
95   const Millisecond & getMaxTimeout() const { return a_maxTimeout; }
96
97   /**
98      Deja en suspenso la creacion de pulsos de reloj. Los temporizadores que estuvieran activos
99      en este momento tendran una duracion indeterminada.
100      Para activar el sistema de control de tiempo debe invocarse al metodo play.
101      \warning Si el gestor de tiempo esta en modo pausa no se pueden activar eventos temporales.
102   */
103   void pause() noexcept(false);
104
105   /**
106      Reactiva la creacion de pulsos de reloj despues de la invocacion al metodo pause
107   */
108   void play() noexcept(false);
109
110   /**
111      Activa el evento de tiempo recibido como parametro. Si transcurre el tiempo indicado por
112      TimeEvent::getTimeout y no hemos invocado a #cancel o a cualquier otro metodo que origine
113      el fin del evento de tiempo (#stop o #kill) se invocaria al metodo TimeEvent::expire.
114
115      @param timeEvent Evento de tiempo que vamos a activar.
116   */
117   void activate(TimeEvent* timeEvent) noexcept(false);
118
119   /**
120      Activa el evento de tiempo recibido como parametro. Si transcurre el tiempo indicado por
121      TimeEvent::getTimeout y no hemos invocado a #cancel o a cualquier otro metodo que origine
122      el fin del evento de tiempo (#stop o #kill) se invocar�al metodo TimeEvent::expire.
123
124      @param timeEvent Evento de tiempo que vamos a activar.
125      \warning Si el gestor de tiempo esta en modo pausa no se pueden activar eventos temporales.
126   */
127   void activate(TimeEvent& timeEvent) noexcept(false) { activate(&timeEvent); }
128
129   /**
130      Cancela la ejecucion del evento de tiempo recibido como parametro. Si el evento no esta
131      activado simplemente se ignora.
132
133      @param timeEvent Evento de tiempo que vamos a desactivar.
134      \warning Si el gestor de tiempo esta en modo pausa no se pueden activar eventos temporales.
135   */
136   void cancel(TimeEvent* timeEvent) noexcept(false);
137
138   /**
139      Cancela la ejecucion del evento de tiempo recibido como parametro. Si el evento no esta
140      activado simplemente se ignora.
141
142      @param timeEvent Evento de tiempo que vamos a desactivar.
143   */
144   void cancel(TimeEvent& timeEvent) noexcept(false) { cancel(&timeEvent); }
145
146   /**
147      Obtiene el evento de tiempo asociado al identificador recibido.
148
149      @param eventTimeId Identificador de tiempo del que queremos obtener la referencia al evento de tiempo.
150
151      \return La referencia al evento de tiempo asociado al identificador recibido o NULL en caso de
152      que exista ningn evento que coincida con el identificador.
153   */
154   TimeEvent* getTimeEvent(const TimeEvent::Id eventTimeId) ;
155
156   /**
157      metodo que podemos reescribir para manejar el evento que nos informa de que el controlador de
158      tiempo va a empezar a comprobar eventos de tiempo caducados. Por defecto no hace nada.
159   */
160   virtual void eventBeginQuantum() noexcept(false) {;}
161
162   /**
163      metodo que podemos reescribir para manejar el evento que nos informa de que el controlador de
164      tiempo a terminado de comprobar eventos de tiempo caducados. Por defecto no hace nada.
165
166      @param quantumSize Nmero de eventos procesados en este quantum de tiempo.
167   */
168   virtual void eventEndQuantum(const int quantumSize) noexcept(false) {;}
169
170   /**
171      Devuelve una cadena con la informacion mas relevante de esta instancia.
172      \return Una cadena con la informacion mas relevante de esta instancia.
173   */
174   virtual std::string asString() const ;
175
176   /**
177      Devuelve un documento XML con la informacion mas relevante de esta instancia.
178      \param parent Nodo XML del que colgar la informacion referente a esta instancia.
179      \return Un documento XML con la informacion mas relevante de esta instancia.
180   */
181   virtual xml::Node* asXML(xml::Node* parent) const ;
182
183   /**
184      Devuelve la cadena por la que podemos buscar el componente.
185      \return La cadena por la que podemos buscar el componente.
186      \see Application::find
187   */
188   static const char* getClassName() { return "anna::timex::Engine"; }
189
190 private:
191   typedef std::vector <TimeEvent*> Quantum;
192   typedef Quantum::iterator quantum_iterator;
193   typedef std::map <TimeEvent::Id, Quantum*> Directory;
194
195   Quantum* a_timeTable;
196   Engine::Directory a_directory;
197   int a_currentQuantum;
198   int a_maxQuantum;
199   Millisecond a_resolution;
200   Millisecond a_maxTimeout;
201   bool a_isActive;
202   TickProducer* a_tickProducer;
203   TickConsumer* a_tickConsumer;
204   Thread* a_thread;
205   Quantum* a_expiredQuantum;
206   Quantum a_delayedQuantum;
207   pthread_t a_threadProducer;
208
209   void do_initialize() noexcept(false);
210   void do_stop() ;
211   void kill() ;
212
213   void tick() noexcept(false);
214   int getQuantum(const int timeout) const { return (a_currentQuantum + (timeout / a_resolution)) % a_maxQuantum; }
215   void calibrate() ;
216
217   // Reimplementado de app::Component
218   void do_cloneParent() ;
219   void do_cloneChild() noexcept(false);
220
221   static void notifyRelease(TimeEvent* timeEvent) ;
222   static TimeEvent* timeEvent(quantum_iterator& ii) { return *ii; }
223
224   friend class TickProducer;
225   friend class TickConsumer;
226   friend class st::TickProducer;
227   friend class mt::TickProducer;
228 };
229
230 }
231 }
232
233 #endif
234
235