Remove dynamic exceptions
[anna.git] / source / timex / internal / TickConsumer.cpp
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 #include <unistd.h>
10 #include <fcntl.h>
11 #include <stdlib.h>
12 #include <sys/types.h>
13
14 #include <anna/core/tracing/Logger.hpp>
15
16 #include <anna/timex/Engine.hpp>
17 #include <anna/timex/internal/TickConsumer.hpp>
18 #include <anna/timex/internal/TickProducer.hpp>
19
20 using namespace std;
21 using namespace anna;
22
23 //--------------------------------------------------------------------------------------------
24 // (1) Para evitar que el 'write' sobre el pipe se pueda quedar bloqueado cuando halla algn
25 //     problema. Se detecto el bloqueo cuando el disco sobre el que se ejecutaba la aplicacin
26 //     se llenaba.
27 // (2) Puede ser que se invoque mas de una vez.
28 //--------------------------------------------------------------------------------------------
29 void anna::timex::TickConsumer::initialize()
30 noexcept(false) {
31   if(a_pipe [0] != -1)                                        // (2)
32     return;
33
34   if(pipe(a_pipe) != 0)
35     throw RuntimeException("Cannot create the pipe", errno, ANNA_FILE_LOCATION);
36
37   if(fcntl(a_pipe [1], F_SETFL, O_NONBLOCK | O_NDELAY) == -1)    // (1)
38     throw RuntimeException("Cannot establish Non-Block mode on pipe", errno, ANNA_FILE_LOCATION);
39
40   setfd(a_pipe [0]);
41 }
42
43 void anna::timex::TickConsumer::apply()
44 noexcept(false) {
45   char buffer [256];
46
47   if(a_pipe [0] == -1)
48     return;
49
50   int r;
51
52   try {
53     anna_signal_shield(r, read(a_pipe [0], buffer, sizeof(buffer)));
54
55     if(r < 0)
56       Logger::write(Logger::Critical, "Cannot recover the tick", strerror(errno), ANNA_FILE_LOCATION);
57
58     while(r > 0) {
59       a_timeController.tick();
60       r --;
61     }
62   } catch(Exception& ex) {
63     ex.trace();
64   }
65 }
66
67 void anna::timex::TickConsumer::finalize()
68 {
69   if(a_timeController.a_tickProducer)
70     a_timeController.a_tickProducer->requestStop();
71 }
72
73 /**
74  * Si usaramos directamente el duplicado de los fd's que hace fork, todos los procesos compartirian el
75  * mismo pipe, es decir, el proceso padre podria escribir al generar la alarma, pero el tratamiento del
76  * tick podria hacerlo el tercer hijo, lo que haria imposible el correcto funcionamiento de las transaciones.
77  *
78  * Asi que cada proceso debe tener su propia copia del pipe, para que cada uno lleve independientemente
79  * el control de tiempos.
80  */
81 void anna::timex::TickConsumer::clone()
82 noexcept(false) {
83   close(a_pipe [0]);
84   close(a_pipe [1]);
85
86   if(pipe(a_pipe) != 0)
87     throw RuntimeException("Cannot create the pipe", errno, ANNA_FILE_LOCATION);
88
89   if(fcntl(a_pipe [1], F_SETFL, O_NONBLOCK | O_NDELAY) == -1)    // (1)
90     throw RuntimeException("Cannot establish Non-Block mode on pipe", errno, ANNA_FILE_LOCATION);
91
92   setfd(a_pipe [0]);
93
94   if(a_timeController.a_tickProducer)
95     a_timeController.a_tickProducer->setfd(a_pipe [1]);
96 }
97
98 std::string anna::timex::TickConsumer::asString() const
99 {
100   string result("timex::TickConsumer { ");
101   result += Handler::asString();
102   return result += functions::asString(" | Pipe (Read = %d, Write = %d) } ", a_pipe [0], a_pipe [1]);
103 }
104
105