1 // ANNA - Anna is Not 'N' Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // https://bitbucket.org/testillano/anna
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
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
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.
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.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
37 #ifndef anna_timex_Engine_hpp
38 #define anna_timex_Engine_hpp
45 #include <anna/app/Component.hpp>
47 #include <anna/timex/TimeEvent.hpp>
67 Controlador general de tiempos.
69 El siguiente ejemplo muestra como obtener la instancia del gestor de tiempo asociado a nuestra aplicacion:
73 #include <anna.timex.Engine.h>
75 void cualquierFuncion (Timer* timer)
76 throw (RuntimeException)
78 Engine* timeController = anna::component <Engine> (FILE_LOCATION);
79 timerController->activate (timer);
82 Si el componente Engine no hubiera sido registrado (instanciado) en nuestra aplicacion el metodo
83 template anna::component lanzara una excepcion.
90 class Engine : public app::Component {
93 Resolucion minima (en milisegundos) soportada por el controlador de tiempos.
95 static const Millisecond minResolution;
100 Asocia automatica el objeto controlador de tiempo a la instancia de nuestra aplicacin.
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.
106 Engine(const Millisecond & maxTimeout, const Millisecond & resolution);
114 Devuelve la resolucion del controlador de tiempo indicada en el contructor.
115 \return la resolucion del controlador de tiempo indicada en el contructor.
117 const Millisecond & getResolution() const throw() { return a_resolution; }
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.
123 const Millisecond & getMaxTimeout() const throw() { return a_maxTimeout; }
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.
131 void pause() throw(RuntimeException);
134 Reactiva la creacion de pulsos de reloj despues de la invocacion al metodo pause
136 void play() throw(RuntimeException);
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.
143 @param timeEvent Evento de tiempo que vamos a activar.
145 void activate(TimeEvent* timeEvent) throw(RuntimeException);
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.
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.
155 void activate(TimeEvent& timeEvent) throw(RuntimeException) { activate(&timeEvent); }
158 Cancela la ejecucion del evento de tiempo recibido como parametro. Si el evento no esta
159 activado simplemente se ignora.
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.
164 void cancel(TimeEvent* timeEvent) throw(RuntimeException);
167 Cancela la ejecucion del evento de tiempo recibido como parametro. Si el evento no esta
168 activado simplemente se ignora.
170 @param timeEvent Evento de tiempo que vamos a desactivar.
172 void cancel(TimeEvent& timeEvent) throw(RuntimeException) { cancel(&timeEvent); }
175 Obtiene el evento de tiempo asociado al identificador recibido.
177 @param eventTimeId Identificador de tiempo del que queremos obtener la referencia al evento de tiempo.
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.
182 TimeEvent* getTimeEvent(const TimeEvent::Id eventTimeId) throw();
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.
188 virtual void eventBeginQuantum() throw(RuntimeException) {;}
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.
194 @param quantumSize Nmero de eventos procesados en este quantum de tiempo.
196 virtual void eventEndQuantum(const int quantumSize) throw(RuntimeException) {;}
199 Devuelve una cadena con la informacion mas relevante de esta instancia.
200 \return Una cadena con la informacion mas relevante de esta instancia.
202 virtual std::string asString() const throw();
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.
209 virtual xml::Node* asXML(xml::Node* parent) const throw();
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
216 static const char* getClassName() { return "anna::timex::Engine"; }
219 typedef std::vector <TimeEvent*> Quantum;
220 typedef Quantum::iterator quantum_iterator;
221 typedef std::map <TimeEvent::Id, Quantum*> Directory;
223 Quantum* a_timeTable;
224 Engine::Directory a_directory;
225 int a_currentQuantum;
227 Millisecond a_resolution;
228 Millisecond a_maxTimeout;
230 TickProducer* a_tickProducer;
231 TickConsumer* a_tickConsumer;
233 Quantum* a_expiredQuantum;
234 Quantum a_delayedQuantum;
235 pthread_t a_threadProducer;
237 void do_initialize() throw(RuntimeException);
238 void do_stop() throw();
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();
245 // Reimplementado de app::Component
246 void do_cloneParent() throw();
247 void do_cloneChild() throw(RuntimeException);
249 static void notifyRelease(TimeEvent* timeEvent) throw();
250 static TimeEvent* timeEvent(quantum_iterator& ii) throw() { return *ii; }
252 friend class TickProducer;
253 friend class TickConsumer;
254 friend class st::TickProducer;
255 friend class mt::TickProducer;