Fix local server for multiple applications
[anna.git] / mt / SafeRecycler.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_core_mt_SafeRecycler_hpp
10 #define anna_core_mt_SafeRecycler_hpp
11
12 #include <stack>
13 #include <vector>
14 #include <algorithm>
15 #include <typeinfo>
16
17 #include <anna/core/RuntimeException.hpp>
18 #include <anna/core/mt/Mutex.hpp>
19 #include <anna/core/Allocator.hpp>
20 #include <anna/core/mt/Guard.hpp>
21 #include <anna/core/util/Recycler.hpp>
22
23 namespace anna {
24
25 /**
26    Mantiene una lista de punteros que puede crecer dinamicamente, no obstante, siempre que sea posible
27    intenta reusar punteros creados previamente.
28
29    Establece secciones critidas para acceder a los datos.
30
31    @param T Clase de la que mantener la lista de punteros pre-asignados.
32    @param Allocator Clase encargada de reservar la memoria para los objetos T en el momento en que sea necesaria
33    una nueva instancia.
34 */
35 template < typename T, typename _Allocator = Allocator <T> >
36 class SafeRecycler : public Recycler <T, _Allocator>, public Mutex {
37 public:
38   typedef typename Recycler <T, _Allocator>::iterator iterator;
39   typedef typename Recycler <T, _Allocator>::const_iterator const_iterator;
40
41   /**
42      Constructor.
43      \param randomAccess Indicador que permite activar el uso de estructuras de datos adicionales
44      Se ha comprobado que si necesitamos tratar en torno a un centenar de instancias
45      es más eficiente no activar las estructuras para acceso directo, para más objetos resulta
46      imprescinble.
47   */
48   SafeRecycler(const bool randomAccess = false) : Recycler <T, _Allocator> (randomAccess)  {;}
49
50   /**
51      Destructor.
52   */
53   virtual ~SafeRecycler() { ; }
54
55   /**
56      Devuelve un puntero de tipo T. Solo crearia una nueva instancia de la clase T si al invocar a este
57      metoodo no existe ninguna otra instancia que se pueda reutilizar, en cuyo caso haria una nueva reserva.
58
59      Cada una de las llamadas a este metodo debe tener su correspondiente llamada al metodo  #release cuando
60      el puntero deje de ser util.
61
62      @return Un puntero a una instancia de tipo T.
63   */
64   T* create()
65   throw(RuntimeException) {
66     std::string name(typeid(*this).name());
67     name += "::create";
68     Guard guard(this, name.c_str());
69     return Recycler <T, _Allocator>::create();
70   }
71
72   /**
73      Devuelve el iterador que apunta al objeto recibido como parametro.
74      \return el iterador que apunta al objeto recibido como parametro.
75   */
76   iterator find(T* t)
77   throw(RuntimeException) {
78     std::string name(typeid(*this).name());
79     name += "::find";
80     Guard guard(this, name.c_str());
81     return Recycler <T, _Allocator>::find(t);
82   }
83
84   /**
85      Libera el puntero recibido como parametro. No se libera fisicamente sino que se deja marcado como
86      reusable.
87
88      Si el puntero pasado como parametro no ha sido obtenido mediante el metodo #create los resultados
89      no estan definidos.
90
91      @param t Instancia de un puntero de tipo T obtenido a partir del metodo #create.
92   */
93   void release(T* t)
94   throw() {
95     if(t == NULL)
96       return;
97
98     try {
99       std::string name(typeid(*this).name());
100       name += "::release (T*)";
101       Guard guard(this, name.c_str());
102       Recycler <T, _Allocator>::release(t);
103     } catch(Exception& ex) {
104       ex.trace();
105     }
106   }
107
108   /**
109      Libera el puntero asociado al iterador recibido como parametro.
110      \param ii Instancia a liberar.
111   */
112   void release(iterator& ii) throw() {
113     try {
114       std::string name(typeid(*this).name());
115       name += "::release (iterator)";
116       Guard guard(this, name.c_str());
117       Recycler <T, _Allocator>::release(ii);
118     } catch(Exception& ex) {
119       ex.trace();
120     }
121   }
122
123   /**
124      Libera el puntero recibido como parametro. No se libera fisicamente sino que se deja marcado como
125      reusable.
126
127      Si el puntero pasado como parametro no ha sido obtenido mediante el metodo #create los resultados
128      no estan definidos.
129
130      @param t Instancia de un puntero de tipo T obtenido a partir del metodo #create.
131   */
132   void release(const T* t) throw() { release(const_cast <T*>(t)); }
133
134   /**
135      Marca como disponibles todos los objetos contenidos en memoria.
136   */
137   void clear()
138   throw() {
139     std::string name(typeid(*this).name());
140     name += "::clear";
141     Guard guard(this, name.c_str());
142     Recycler <T, _Allocator>::clear();
143   }
144 };
145
146 }
147
148 #endif
149