Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
tpl_concurrent_graph.H
1 # ifndef TPL_CONCURRENT_GRAPH_H
2 # define TPL_CONCURRENT_GRAPH_H
3 
4 # include <pthread.h>
5 
6 # include <autosprintf.h>
7 
8 # include <gsl/gsl_rng.h>
9 # include <gsl/gsl_randist.h>
10 
11 # include <tpl_graph.H>
12 # include <useMutex.H>
13 
14 using namespace Aleph;
15 
16 
17 namespace Aleph
18 {
19 
20 
21  template <template <class, class> class GT, class __Node, class __Arc>
23 
34  template <class Base_Object>
35 class Lock_Object : public Base_Object
36 {
37 public:
38 
39  pthread_mutex_t * mutex; // protege toda la data asociada al nodo
40 
41  typedef typename Base_Object::Item_Type Object_Type;
42 
43  Lock_Object(const Lock_Object & c_obj)
44  : Base_Object(c_obj) , mutex(c_obj.mutex)
45  {
46  I(not c_obj.delete_mutex);
47  }
48 
49  Lock_Object(pthread_mutex_t * __mutex = NULL)
50  : Base_Object(), mutex(__mutex)
51  {
52  // empty
53  }
54 
55  Lock_Object(const Object_Type & obj_info, pthread_mutex_t * __mutex = NULL)
56  : Base_Object(obj_info), mutex(__mutex)
57  {
58  // Empty
59  }
60 
61  Lock_Object(Base_Object * pobj, pthread_mutex_t * __mutex = NULL)
62  : Base_Object(pobj) , mutex(__mutex)
63  {
64  // Empty
65  }
66 
67  void set_mutex( pthread_mutex_t * ptrm)
68  {
69  mutex = ptrm;
70  }
71 
72  void set_mutex(pthread_mutex_t & m)
73  {
74  mutex = &m;
75  }
76 
81  class Critical_Section : public UseMutex
82  {
83  public:
84 
87  : UseMutex(node->mutex) { /* empty */ }
88  };
89 };
90 
91 
138  template <template <class, class> class __GT, class __Node, class __Arc>
139 class Concurrent_Graph : public __GT<Lock_Object<__Node>, Lock_Object<__Arc> >
140 {
141 public:
142 
143  typedef __GT<Lock_Object<__Node>, Lock_Object<__Arc> > GT;
144 
145  typedef typename GT::Node Node;
146 
147  typedef typename GT::Arc Arc;
148 
149 protected:
150 
151  pthread_mutex_t mutex;
152 
153  size_t num_mutexes;
154 
156 
157  void init_mutexes()
158  {
159  mutexes.reserve(num_mutexes);
160  for (int i = 0; i < num_mutexes; ++i)
161  init_mutex(&mutexes.access(i));
162  }
163 
164  void uninit_mutexes()
165  {
166  for (int i = 0; i < num_mutexes; ++i)
167  destroy_mutex(&mutexes.access(i));
168  }
169 
170 public:
171 
172  pthread_mutex_t * get_mutex(int i)
173  {
174  if (i >= num_mutexes)
175  throw std::out_of_range(gnu::autosprintf("mutex index %d out of range", i));
176 
177  return mutexes.access(i);
178  }
179 
180  pthread_mutex_t * allocate_mutex()
181  {
182  init_mutex(&mutexes.append());
183 
184  return mutexes.access(num_mutexes++);
185  }
186 
188  typedef typename GT::Node_Type Node_Type;
189 
191  typedef typename GT::Arc_Type Arc_Type;
192 
194  Concurrent_Graph(const size_t & n_mut = 1) : GT(), num_mutexes(n_mut)
195  {
196  init_mutex(mutex);
197  init_mutexes();
198  }
199 
201  Concurrent_Graph(const Concurrent_Graph & g) : GT(g), num_mutexes(g.num_mutexes)
202  {
203  init_mutex(mutex);
204  init_mutexes();
205  }
206 
207  void set_num_mutexes(const size_t & n)
208  {
209  CRITICAL_SECTION(mutex);
210 
211  if (n == 0)
212  throw std::out_of_range("n is equal to zero");
213 
214  if (n < num_mutexes)
215  throw std::out_of_range("n is smaller than current number of mutexes");
216 
217  mutexes.reserve(n);
218 
219  for (int i = num_mutexes; i < n; ++i)
220  init_mutex(&mutexes.access(i));
221 
222  num_mutexes = n;
223  }
224 
225  void distribute_mutexes_randomly()
226  {
227  gsl_rng * r = gsl_rng_alloc (gsl_rng_mt19937);
228  gsl_rng_set(r, time(NULL) % gsl_rng_max(r));
229 
230  for (typename Concurrent_Graph::Node_Iterator it(*this); it.has_current();
231  it.next())
232  {
233  int i = gsl_rng_uniform_int(r, num_mutexes); // índice del mutex al azar
234  it.get_current()->set_mutex(mutexes.access(i));
235  }
236 
237  for (typename Concurrent_Graph::Arc_Iterator it(*this); it.has_current();
238  it.next())
239  {
240  int i = gsl_rng_uniform_int(r, num_mutexes); // índice del mutex al azar
241  it.get_current()->set_mutex(mutexes.access(i));
242  }
243 
244  gsl_rng_free(r);
245  }
246 
247  void distribute_mutexes_uniformly()
248  {
249  {
250  const size_t & num_nodes = this->get_num_nodes();
251  const size_t num_nodes_by_mutex = num_nodes / num_mutexes;
252 
253  typename GT::Node_Iterator it(*this);
254  for (int k = 0; k < num_nodes_by_mutex; ++k)
255  {
256  pthread_mutex_t & m = mutexes.access(k);
257 
258  for (int i = 0; it.has_current() and i < num_nodes; ++i, it.next())
259  it.get_current()->set_mutex(m);
260  }
261  }
262 
263  {
264  const size_t & num_arcs = this->get_num_arcs();
265  const size_t num_arcs_by_mutex = num_arcs / num_mutexes;
266 
267  typename GT::Arc_Iterator it(*this);
268  for (int k = 0; k < num_arcs_by_mutex; ++k)
269  {
270  pthread_mutex_t & m = mutexes.access(k);
271 
272  for (int i = 0; it.has_current() and i < num_arcs; ++i, it.next())
273  it.get_current()->set_mutex(m);
274  }
275  }
276  }
277 
278  virtual ~Concurrent_Graph()
279  {
280  uninit_mutexes();
281  destroy_mutex(mutex);
282  }
283 
289  {
290  Concurrent_Graph & cg;
291 
292  typename GT::Node_Iterator base_iterator;
293 
294  public:
295 
296  typedef typename GT::Node_Iterator::Item_Type Item_Type;
297 
298  Node_Iterator() : base_iterator()
299  {
300  // empty
301  }
302 
304  Node_Iterator(Concurrent_Graph & _g) : cg(_g), base_iterator(_g)
305  {
306  // empty
307  }
308 
311  : cg(it.cg), base_iterator(it.base_iterator)
312  {
313  // empty
314  }
315 
318  {
319  CRITICAL_SECTION(cg.mutex);
320 
321  if (&it == this)
322  return *this;
323 
324  base_iterator = it.base_iterator;
325 
326  return *this;
327  }
328 
331  {
332  CRITICAL_SECTION(cg.mutex);
333 
334  Node * node = base_iterator.get_current_node();
335 
336  return node;
337  }
338 
340  Node * get_current() { return get_current_node(); }
341 
343  bool has_current()
344  {
345  CRITICAL_SECTION(cg.mutex);
346  return base_iterator.has_current();
347  }
348 
350  void next()
351  {
352  CRITICAL_SECTION(cg.mutex);
353  base_iterator.next();
354  }
355 
357  void prev()
358  {
359  CRITICAL_SECTION(cg.mutex);
360  base_iterator.prev();
361  }
362 
364  void reset_first()
365  {
366  CRITICAL_SECTION(cg.mutex);
367  base_iterator.reset_first();
368  }
369 
371  void reset_last()
372  {
373  CRITICAL_SECTION(cg.mutex);
374  base_iterator.reset_last();
375  }
376  };
377 
383  {
384  Concurrent_Graph & cg;
385 
386  typename GT::Arc_Iterator base_iterator;
387 
388  public:
389 
390  typedef typename GT::Node_Iterator::Item_Type Item_Type;
391 
393  Arc_Iterator() : base_iterator()
394  {
395  // empty
396  }
397 
399  Arc_Iterator(Concurrent_Graph & _g) : cg(_g), base_iterator(_g)
400  {
401  // empty
402  }
403 
404  Arc_Iterator(const Arc_Iterator & it)
405  : cg(it.cg), base_iterator(it.base_iterator)
406  {
407  // empty
408  }
409 
412  {
413  CRITICAL_SECTION(cg.mutex);
414 
415  base_iterator = it.base_iterator;
416 
417  return *this;
418  }
419 
422  {
423  CRITICAL_SECTION(cg.mutex);
424 
425  Arc * arc = base_iterator.get_current_arc();
426 
427  return arc;
428  }
429 
431  Arc * get_current() { return get_current_arc(); }
432 
434  bool has_current()
435  {
436  CRITICAL_SECTION(cg.mutex);
437  return base_iterator.has_current();
438  }
439 
441  void next()
442  {
443  CRITICAL_SECTION(cg.mutex);
444  base_iterator.next();
445  }
446 
448  void prev()
449  {
450  CRITICAL_SECTION(cg.mutex);
451  base_iterator.prev();
452  }
453 
455  void reset_first()
456  {
457  CRITICAL_SECTION(cg.mutex);
458  base_iterator.reset_first();
459  }
460 
462  void reset_last()
463  {
464  CRITICAL_SECTION(cg.mutex);
465  base_iterator.reset_last();
466  }
467  };
468 
470  size_t get_num_nodes()
471  {
472  CRITICAL_SECTION(mutex);
473  return GT::get_num_nodes();
474  }
475 
476  // Hace visible get_num_arcs(Node*) heredada de List_Graph
478 
480  size_t get_num_arcs()
481  {
482  CRITICAL_SECTION(mutex);
483  return GT::get_num_arcs();
484  }
485 
486  size_t get_num_mutexes()
487  {
488  CRITICAL_SECTION(mutex);
489  return num_mutexes;
490  }
491 
493  Node * search_node(const Node_Type & node_info)
494  {
495  CRITICAL_SECTION(mutex);
496  return GT::search_node(node_info);
497  }
498 
500  Node * insert_node(Node * node)
501  {
502  CRITICAL_SECTION(mutex);
503  return GT::insert_node(node);
504  }
505 
507  Node * insert_node(const Node_Type & node_info)
508  {
509  return insert_node( new Node(node_info) );
510  }
511 
513  Node * get_first_node()
514  {
515  CRITICAL_SECTION(mutex);
516  return GT::get_first_node();
517  }
518 
520  Arc * get_first_arc()
521  {
522  CRITICAL_SECTION(mutex);
523  return GT::get_first_arc();
524  }
525 
526  void verify_graphs(Concurrent_Graph& g)
527  {
528  CRITICAL_SECTION(mutex);
529  GT::verify_graphs(g);
530  }
531 
533  void remove_node(Node * node)
534  {
535  CRITICAL_SECTION(mutex);
536  GT::remove_node(node);
537  }
538 
540  template <class Compare> void sort_arcs()
541  {
542  CRITICAL_SECTION(mutex);
543  GT::template sort_arcs<Compare> ();
544  }
545 
547  Arc * insert_arc(Node * src_node,
548  Node * tgt_node,
549  const Arc_Type & arc_info)
550  {
551  CRITICAL_SECTION(mutex);
552  return GT::insert_arc(src_node, tgt_node, arc_info);
553  }
554 
556  Arc * insert_arc(Node * src_node,
557  Node * tgt_node)
558  {
559  CRITICAL_SECTION(mutex);
560  return GT::insert_arc(src_node, tgt_node);
561  }
562 
564  void remove_arc(Arc * arc)
565  {
566  CRITICAL_SECTION(mutex);
567  GT::remove_arc(arc);
568  }
569 
571  Arc * search_arc(Node * src_node, Node * tgt_node)
572  {
573  CRITICAL_SECTION(mutex);
574  return GT::search_arc(src_node, tgt_node);
575  }
576 
578  Arc * search_arc(const Arc_Type & arc_info)
579  {
580  CRITICAL_SECTION(mutex);
581  return GT::search_arc(arc_info);
582  }
583 
585  bool arc_belong_to_graph(Arc * arc)
586  {
587  CRITICAL_SECTION(mutex);
588  return GT::arc_belong_to_graph(arc);
589  }
590 };
591 
592 }
593 
594 # endif // TPL_CONCURRENT_GRAPH_H
bool has_current()
Retorna true si el iterador tiene elemento actual.
Definition: tpl_concurrent_graph.H:343
void reset_first()
Reinicia el iterador al primer nodo.
Definition: tpl_concurrent_graph.H:364
void reserve(const size_t l, const size_t r)
Definition: tpl_dynArray.H:960
Node * insert_node(const Node_Type &node_info)
Crea e inserta un nuevo nodo con información node_info.
Definition: tpl_concurrent_graph.H:507
Node * insert_node(Node *node)
Inserta un nodo ya creado en un grafo.
Definition: tpl_concurrent_graph.H:500
Definition: tpl_concurrent_graph.H:22
Definition: tpl_graph.H:29
GT::Node_Type Node_Type
El tipo de nodo concurrente.
Definition: tpl_concurrent_graph.H:188
Arc * get_current_arc()
Obtiene el arco actual del iterador.
Definition: tpl_concurrent_graph.H:421
void prev()
Retrocede el iterador en una posición.
Definition: tpl_concurrent_graph.H:448
Arc_Iterator()
Instancia un iterador vacío.
Definition: tpl_concurrent_graph.H:393
Concurrent_Graph(const Concurrent_Graph &g)
Instancia un grafo concurrente copia de otro grafo concurrente.
Definition: tpl_concurrent_graph.H:201
Node * get_current()
Retorna el nodo actual.
Definition: tpl_concurrent_graph.H:340
Arc * search_arc(Node *src_node, Node *tgt_node)
Busca un arco que conecte a dos nodos.
Definition: tpl_concurrent_graph.H:571
Node * get_first_node()
Retorna el primer nodo de un grafo; no hay un orden determinado.
Definition: tpl_concurrent_graph.H:513
void remove_node(Node *node)
Elimina un nodo de un grafo (junto con todos sus arcos adyacentes).
Definition: tpl_concurrent_graph.H:533
void reset_first()
Reincia el iterador al primer arco.
Definition: tpl_concurrent_graph.H:455
Arc * insert_arc(Node *src_node, Node *tgt_node, const Arc_Type &arc_info)
Crea un arco en un grafo concurrente.
Definition: tpl_concurrent_graph.H:547
Arc_Iterator & operator=(const Arc_Iterator &it)
Instancia un iterador copia del iterador it.
Definition: tpl_concurrent_graph.H:411
Definition: tpl_concurrent_graph.H:35
void next()
Avanza el iterador en una posición.
Definition: tpl_concurrent_graph.H:441
size_t get_num_nodes()
Retorna el número de nodos que tiene el grafo concurrente.
Definition: tpl_concurrent_graph.H:470
Node * get_current_node()
Retorna el nodo actual.
Definition: tpl_concurrent_graph.H:330
void remove_arc(Arc *arc)
Elimina un arco en un grafo concurrente.
Definition: tpl_concurrent_graph.H:564
Arc_Iterator(Concurrent_Graph &_g)
Instancia un iterador sobre los arcos del grafo concurrente _g.
Definition: tpl_concurrent_graph.H:399
void reset_last()
Reincia el iterador al último arco.
Definition: tpl_concurrent_graph.H:462
bool has_current()
Retorna true si el iterador tiene arco actual.
Definition: tpl_concurrent_graph.H:434
Definition: useMutex.H:20
GT::Arc_Type Arc_Type
El tipo de arco concurrente.
Definition: tpl_concurrent_graph.H:191
Arc * search_arc(const Arc_Type &arc_info)
Busca un arco con información arc_info.
Definition: tpl_concurrent_graph.H:578
T & append()
Definition: tpl_dynArray.H:1115
Definition: tpl_concurrent_graph.H:382
bool arc_belong_to_graph(Arc *arc)
Retorna true si el arco arc pertenece al grafo.
Definition: tpl_concurrent_graph.H:585
void sort_arcs()
ordena los arcos de un grafo concurrente según criterio Compare.
Definition: tpl_concurrent_graph.H:540
Critical_Section(Lock_Object *node)
Toma sección crítica del nodo node. Se libera en destrucción.
Definition: tpl_concurrent_graph.H:86
Arc * get_first_arc()
Retorna el primer arco de un grafo.
Definition: tpl_concurrent_graph.H:520
size_t get_num_arcs()
Retorna el número de arcos que tiene el grafo concurrente.
Definition: tpl_concurrent_graph.H:480
Definition: tpl_concurrent_graph.H:81
void prev()
Retrocede el iterador en una posición.
Definition: tpl_concurrent_graph.H:357
GT::Arc * search_arc(GT &g, typename GT::Node *src_node, typename GT::Node *tgt_node)
Definition: tpl_graph.H:2461
Definition: tpl_concurrent_graph.H:288
T & access(const size_t i)
Definition: tpl_dynArray.H:793
Concurrent_Graph(const size_t &n_mut=1)
Instancia un grafo concurrente vacío.
Definition: tpl_concurrent_graph.H:194
Arc * insert_arc(Node *src_node, Node *tgt_node)
Crea un arco en un grafo concurrente.
Definition: tpl_concurrent_graph.H:556
Node_Iterator & operator=(const Node_Iterator &it)
Asigna iterador.
Definition: tpl_concurrent_graph.H:317
Arc * get_current()
Obtiene el arco actual del iterador.
Definition: tpl_concurrent_graph.H:431
Node_Iterator(const Node_Iterator &it)
Instancia un iterador copia del iterador it.
Definition: tpl_concurrent_graph.H:310
Node_Iterator(Concurrent_Graph &_g)
instancia un iterador sobre el grafo _g.
Definition: tpl_concurrent_graph.H:304
void reset_last()
Reinicia el iterador al último nodo.
Definition: tpl_concurrent_graph.H:371
Node * search_node(const Node_Type &node_info)
Busca un nodo según su información contenida.
Definition: tpl_concurrent_graph.H:493
void next()
Avanza el iterador en una posición.
Definition: tpl_concurrent_graph.H:350

Leandro Rabindranath León