Updated license
[anna.git] / include / anna / timex / Engine.hpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_timex_Engine_hpp
38 #define anna_timex_Engine_hpp
39
40 #include <pthread.h>
41
42 #include <vector>
43 #include <map>
44
45 #include <anna/app/Component.hpp>
46
47 #include <anna/timex/TimeEvent.hpp>
48
49 namespace anna {
50
51 class Thread;
52
53 namespace timex {
54
55 class TickProducer;
56 class TickConsumer;
57
58 namespace st {
59 class TickProducer;
60 }
61
62 namespace mt {
63 class TickProducer;
64 }
65
66 /**
67    Controlador general de tiempos.
68
69    El siguiente ejemplo muestra como obtener la instancia del gestor de tiempo asociado a nuestra aplicacion:
70
71    \code
72
73    #include <anna.timex.Engine.h>
74
75    void cualquierFuncion (Timer* timer)
76       throw (RuntimeException)
77    {
78       Engine* timeController = anna::component <Engine> (FILE_LOCATION);
79       timerController->activate (timer);
80    }
81
82    Si el componente Engine no hubiera sido registrado (instanciado) en nuestra aplicacion el metodo
83    template anna::component lanzara una excepcion.
84
85    \endcode
86
87    \see anna::Component
88 */
89
90 class Engine : public app::Component {
91 public:
92   /**
93      Resolucion minima (en milisegundos) soportada por el controlador de tiempos.
94   */
95   static const Millisecond minResolution;
96
97   /**
98      Constructor.
99
100      Asocia automatica el objeto controlador de tiempo a la instancia de nuestra aplicacin.
101
102      @param maxTimeout minima duracion de los eventos de tiempo que vamos a establecer.
103      @param resolution Resolucion ofrecida para este controlador de tiempos. La duracion minima
104      de un evento de tiempo de ser igual o mayor a este parametro.
105   */
106   Engine(const Millisecond & maxTimeout, const Millisecond & resolution);
107
108   /**
109      Destructor
110   */
111   virtual ~Engine();
112
113   /**
114      Devuelve la resolucion del controlador de tiempo indicada en el contructor.
115      \return la resolucion del controlador de tiempo indicada en el contructor.
116   */
117   const Millisecond & getResolution() const throw() { return a_resolution; }
118
119   /**
120      Devuelve el periodo máximo de temporización indicado en el constructor.
121      \return el periodo máximo de temporización indicado en el constructor.
122   */
123   const Millisecond & getMaxTimeout() const throw() { return a_maxTimeout; }
124
125   /**
126      Deja en suspenso la creacion de pulsos de reloj. Los temporizadores que estuvieran activos
127      en este momento tendran una duracion indeterminada.
128      Para activar el sistema de control de tiempo debe invocarse al metodo play.
129      \warning Si el gestor de tiempo esta en modo pausa no se pueden activar eventos temporales.
130   */
131   void pause() throw(RuntimeException);
132
133   /**
134      Reactiva la creacion de pulsos de reloj despues de la invocacion al metodo pause
135   */
136   void play() throw(RuntimeException);
137
138   /**
139      Activa el evento de tiempo recibido como parametro. Si transcurre el tiempo indicado por
140      TimeEvent::getTimeout y no hemos invocado a #cancel o a cualquier otro metodo que origine
141      el fin del evento de tiempo (#stop o #kill) se invocaria al metodo TimeEvent::expire.
142
143      @param timeEvent Evento de tiempo que vamos a activar.
144   */
145   void activate(TimeEvent* timeEvent) throw(RuntimeException);
146
147   /**
148      Activa el evento de tiempo recibido como parametro. Si transcurre el tiempo indicado por
149      TimeEvent::getTimeout y no hemos invocado a #cancel o a cualquier otro metodo que origine
150      el fin del evento de tiempo (#stop o #kill) se invocar�al metodo TimeEvent::expire.
151
152      @param timeEvent Evento de tiempo que vamos a activar.
153      \warning Si el gestor de tiempo esta en modo pausa no se pueden activar eventos temporales.
154   */
155   void activate(TimeEvent& timeEvent) throw(RuntimeException) { activate(&timeEvent); }
156
157   /**
158      Cancela la ejecucion del evento de tiempo recibido como parametro. Si el evento no esta
159      activado simplemente se ignora.
160
161      @param timeEvent Evento de tiempo que vamos a desactivar.
162      \warning Si el gestor de tiempo esta en modo pausa no se pueden activar eventos temporales.
163   */
164   void cancel(TimeEvent* timeEvent) throw(RuntimeException);
165
166   /**
167      Cancela la ejecucion del evento de tiempo recibido como parametro. Si el evento no esta
168      activado simplemente se ignora.
169
170      @param timeEvent Evento de tiempo que vamos a desactivar.
171   */
172   void cancel(TimeEvent& timeEvent) throw(RuntimeException) { cancel(&timeEvent); }
173
174   /**
175      Obtiene el evento de tiempo asociado al identificador recibido.
176
177      @param eventTimeId Identificador de tiempo del que queremos obtener la referencia al evento de tiempo.
178
179      \return La referencia al evento de tiempo asociado al identificador recibido o NULL en caso de
180      que exista ningn evento que coincida con el identificador.
181   */
182   TimeEvent* getTimeEvent(const TimeEvent::Id eventTimeId) throw();
183
184   /**
185      metodo que podemos reescribir para manejar el evento que nos informa de que el controlador de
186      tiempo va a empezar a comprobar eventos de tiempo caducados. Por defecto no hace nada.
187   */
188   virtual void eventBeginQuantum() throw(RuntimeException) {;}
189
190   /**
191      metodo que podemos reescribir para manejar el evento que nos informa de que el controlador de
192      tiempo a terminado de comprobar eventos de tiempo caducados. Por defecto no hace nada.
193
194      @param quantumSize Nmero de eventos procesados en este quantum de tiempo.
195   */
196   virtual void eventEndQuantum(const int quantumSize) throw(RuntimeException) {;}
197
198   /**
199      Devuelve una cadena con la informacion mas relevante de esta instancia.
200      \return Una cadena con la informacion mas relevante de esta instancia.
201   */
202   virtual std::string asString() const throw();
203
204   /**
205      Devuelve un documento XML con la informacion mas relevante de esta instancia.
206      \param parent Nodo XML del que colgar la informacion referente a esta instancia.
207      \return Un documento XML con la informacion mas relevante de esta instancia.
208   */
209   virtual xml::Node* asXML(xml::Node* parent) const throw();
210
211   /**
212      Devuelve la cadena por la que podemos buscar el componente.
213      \return La cadena por la que podemos buscar el componente.
214      \see Application::find
215   */
216   static const char* getClassName() { return "anna::timex::Engine"; }
217
218 private:
219   typedef std::vector <TimeEvent*> Quantum;
220   typedef Quantum::iterator quantum_iterator;
221   typedef std::map <TimeEvent::Id, Quantum*> Directory;
222
223   Quantum* a_timeTable;
224   Engine::Directory a_directory;
225   int a_currentQuantum;
226   int a_maxQuantum;
227   Millisecond a_resolution;
228   Millisecond a_maxTimeout;
229   bool a_isActive;
230   TickProducer* a_tickProducer;
231   TickConsumer* a_tickConsumer;
232   Thread* a_thread;
233   Quantum* a_expiredQuantum;
234   Quantum a_delayedQuantum;
235   pthread_t a_threadProducer;
236
237   void do_initialize() throw(RuntimeException);
238   void do_stop() throw();
239   void kill() throw();
240
241   void tick() throw(RuntimeException);
242   int getQuantum(const int timeout) const throw() { return (a_currentQuantum + (timeout / a_resolution)) % a_maxQuantum; }
243   void calibrate() throw();
244
245   // Reimplementado de app::Component
246   void do_cloneParent() throw();
247   void do_cloneChild() throw(RuntimeException);
248
249   static void notifyRelease(TimeEvent* timeEvent) throw();
250   static TimeEvent* timeEvent(quantum_iterator& ii) throw() { return *ii; }
251
252   friend class TickProducer;
253   friend class TickConsumer;
254   friend class st::TickProducer;
255   friend class mt::TickProducer;
256 };
257
258 }
259 }
260
261 #endif
262
263