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_sim_agent_graph.H
1 #ifndef TPL_SIM_AGENT_GRAPH_H
2 #define TPL_SIM_AGENT_GRAPH_H
3 
4 #include <iostream>
5 #include <cstdlib>
6 #include <sys/types.h>
7 #include <dlink.H>
8 #include <tpl_concurrent_graph.H>
9 #include <tpl_dynBinHeap.H>
10 #include <useMutex.H>
11 
12 using namespace Aleph;
13 using namespace std;
14 
15 namespace Aleph {
16 
17 #define STOPPED 0
18 #define RUNNING 1
19 #define SUSPENDED 2
20 
21  template <typename Agent_Info> class Sim_Agent;
22 
23  template <typename Node_Info> class Sim_Agent_Node;
24 
25  template <typename Arc_Info> class Sim_Agent_Arc;
26 
27  template <typename Arc_Agents, typename Node_Agents, typename Agent>
29 
30  struct Sim_Event
31  {
32  long actual_time;
33 
34  bool to_be_destroyed;
35 
36  Sim_Event() : actual_time(0) { }
37 
38  Sim_Event(const long & _curr_time) : actual_time(_curr_time)
39  {
40  to_be_destroyed = false;
41  }
42 
43  virtual ~Sim_Event() { }
44 
45  bool operator < (const Sim_Event & event) const
46  {
47  return actual_time > event.actual_time;
48  }
49 
50  virtual void execute_event(void * graph)
51  {
52  graph = NULL;
53 
54  throw
55  domain_error("Debe sobreescribir este método en una clase derivada");
56  }
57  };
58 
60  {
61  bool operator () (Sim_Event * op1, Sim_Event * op2)
62  {
63  return op1->actual_time < op2->actual_time;
64  }
65  };
66 
67  template <typename Agent_Info> struct Sim_Agent : public Sim_Event
68  {
69  typedef void (*Transit) (void *, void *);
70 
71  Agent_Info info;
72  Dlink agent_link;
73  Dlink schedule_link;
74  Dlink location_link;
75  bool in_node;
76  void * location;
77  void * cookie;
78  Transit transit;
79 
80  typedef Agent_Info Agent_Type;
81 
82  Sim_Agent(Agent_Info agent_info, Transit _transit, long actual_time)
83  : Sim_Event(actual_time), info (agent_info), transit(_transit)
84  {
85  // empty
86  }
87 
88  ~Sim_Agent() { /* empty */ }
89 
90  LINKNAME_TO_TYPE (Sim_Agent, agent_link);
91  LINKNAME_TO_TYPE (Sim_Agent, schedule_link);
92  LINKNAME_TO_TYPE (Sim_Agent, location_link);
93 
94  Agent_Info & get_info()
95  {
96  return info;
97  }
98 
99  virtual void execute_event (void * graph)
100  {
101  if (transit != NULL)
102  {
103  transit(graph, this);
104  }
105  }
106  };
107 
108  template <typename Agents_Node_Info>
109  struct Sim_Agent_Node : public Concurrent_Node <Agents_Node_Info>
110  {
111  Dlink agent_list;
112  typedef Concurrent_Node<Agents_Node_Info> Parent_Node;
113  typedef Agents_Node_Info Node_Type;
114  Sim_Agent_Node() : Parent_Node() { }
115  Sim_Agent_Node(const Node_Type & info) : Parent_Node(info) {}
116  ~Sim_Agent_Node(){ }
117  };
118 
119 
120  template <typename Agents_Arc_Info>
121  struct Sim_Agent_Arc : public Concurrent_Arc<Agents_Arc_Info> {
122  Dlink agent_list;
123  typedef Concurrent_Arc<Agents_Arc_Info> Parent_Arc;
124  typedef Agents_Arc_Info Arc_Type;
125  Sim_Agent_Arc() : Parent_Arc() { }
126  virtual ~Sim_Agent_Arc(){ }
127  };
128 
129  template <typename Node,typename Arc, typename Agent >
130  struct Sim_Agent_Graph : public Concurrent_Graph<Node, Arc>
131  {
132  public:
133  typedef Concurrent_Graph< Node, Arc > Parent_Graph;
134  typedef Node Node_Class;
135  typedef Arc Arc_Class;
136  typedef typename Node::Node_Type Node_Type;
137  typedef typename Arc::Arc_Type Arc_Type;
138  typedef typename Agent::Agent_Type Agent_Type;
139 
140  private:
141  size_t thread_count;
142  pthread_t * threads;
143  int status ;
144  pthread_mutex_t sch_mutex;
145  pthread_mutex_t suspend_mutex;
146  pthread_cond_t sch_cond;
147  pthread_cond_t suspend_cond;
148  long actual_time;
149  long callback_rate;
150  typedef void (* Update_Callback) (Sim_Agent_Graph *, Agent *, void *);
151  Update_Callback update_callback;
152 
155  Dlink agent_list; // lista de agentes
156  size_t num_agents;
157 
160 
161  public:
162 
164  const size_t & get_num_agents() const {return num_agents;}
165 
166  Node * get_agent_node_location (Agent * agent)
167  {
168  if (agent->in_node)
169  {
170  return static_cast<Node*>(agent->location);
171  }
172  return NULL;
173  }
174 
175  void set_agent_node_location (Agent * agent, Node * node)
176  {
177  agent->location_link.del();
178  agent->in_node = true;
179  agent->location = node;
180  node->agent_list.append(&agent->location_link);
181  }
182 
183  Arc * get_agent_arc_location (Agent * agent)
184  {
185  if (!agent->in_node)
186  {
187  return static_cast<Arc*>(agent->location);
188  }
189  return NULL;
190  }
191 
192  void set_agent_arc_location(Agent * agent, Arc * arc)
193  {
194  agent->location_link.del();
195  agent->in_node = false;
196  agent->location = arc;
197  arc->agent_list.append(&agent->location_link);
198  }
199 
200  bool is_agent_in_node (Agent * agent)
201  {
202  return agent->in_node;
203  }
204 
205  Agent * get_first_agent ()
206  {
207  if(get_num_agents() == 0)
208  throw std::range_error("Graph has not agents ");
209  return Agent::agent_link_to_Sim_Agent(&*agent_list.get_next());
210  }
211 
212  void remove_agent (Agent * agent)
213  {
214  agent->agent_link.del();
215  agent->location_link.del();
216  num_agents--;
217  delete agent;
218  }
219 
220  void clear_agent_list()
221  {
222  Agent * agent = NULL;
223  for (Dlink::Iterator it(&agent_list); it.has_current(); )
224  {
225  agent = Agent::agent_link_to_Sim_Agent(it.get_current());
226  it.next();
227  remove_agent(agent);
228  }
229  }
230 
233  Sim_Agent_Graph(const size_t & num_threads) : thread_count(num_threads)
234  {
235  threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t));
236  init_mutex(sch_mutex);
237  init_mutex(suspend_mutex);
238  pthread_cond_init(&suspend_cond, NULL);
239  pthread_cond_init(&sch_cond, NULL);
240  status =RUNNING;
241  num_agents = 0;
242  }
243 
244  virtual ~Sim_Agent_Graph()
245  {
246  clear_agent_list();
247  destroy_mutex(sch_mutex);
248  destroy_mutex(suspend_mutex);
249  pthread_cond_destroy(&suspend_cond);
250  pthread_cond_destroy(&sch_cond);
251  free(threads);
252  }
253 
254  Agent * create_agent_in_node(Agent_Type agent_info, void (*funcptr) (void *, void *), Node * node, long activation_time)
255  {
256  Agent * agent = new Agent ( agent_info, funcptr, activation_time );
257  set_agent_node_location(agent, node);
258  agent_list.append(&agent->agent_link);
259  num_agents++;
260  schedule_event(agent);
261  return agent;
262  }
263 
264  Agent * create_agent_in_arc(Agent_Type agent_info, void (*funcptr) (void *, void *), Arc * arc, long activation_time)
265  {
266  Agent * agent = new Agent( agent_info, funcptr, activation_time );
267  set_agent_arc_location(agent, arc);
268  agent_list.append(&agent->agent_link);
269  num_agents++;
270  schedule_event(agent);
271  return agent;
272  }
273 
274  template <class Equal>
275  Agent * search_agent(const Agent_Type & agent)
276  {
277  Agent * result = NULL;
278  for (Dlink::Iterator it(agent_list); it.has_current(); it.next())
279  {
280  result = Agent::agent_link_to_Sim_Agent(it.get_current());
281  if (Equal() (result->get_info(), agent))
282  {
283  return result;
284  }
285  }
286  return NULL;
287  }
288 
289  Agent * search_agent(const Agent_Type & agent)
290  {
291  return search_agent<Aleph::equal_to<Agent_Type> >(agent);
292  }
293 
294  void start_graph()
295  {
296  for (unsigned int i = 0; i < thread_count; i++)
297  {
298  int result = pthread_create(&threads[i] , NULL, Sim_Agent_Graph::run, this);
299  if (result == 0)
300  {
301  cout<<" Thread "<<i<<endl;
302  }
303  }
304  }
305 
306  void stop_graph()
307  {
308  if (get_status() == SUSPENDED)
309  {
310  resume_graph();
311  }
312  set_status(STOPPED);
313  for (unsigned int i = 0; i < thread_count; i++)
314  {
315  pthread_join(threads[i] , NULL);
316  }
317  }
318 
319  int get_status()
320  {
321  CRITICAL_SECTION(sch_mutex);
322  return status;
323  }
324 
325  void set_status(int value)
326  {
327  CRITICAL_SECTION(sch_mutex);
328  status = value;
329  }
330 
331  void suspend_graph()
332  {
333  set_status(SUSPENDED);
334  }
335 
336  void resume_graph()
337  {
338  set_status(RUNNING);
339  pthread_cond_broadcast(&suspend_cond);
340 
341  }
342 
343  void cancel_event(Sim_Event * event)
344  {
345  }
346 
347  void schedule_event (Sim_Event * event)
348  {
349  events_heap.insert(event);
350  }
351 
352  void set_update_callback(Update_Callback fnct)
353  {
354  update_callback = fnct;
355  }
356 
357  long get_actual_time()
358  {
359  return actual_time;
360  }
361 
362  void set_callback_rate(long rate)
363  {
364  callback_rate = rate;
365  }
366 
367  long get_callback_rate()
368  {
369  return callback_rate();
370  }
371 
372  static void * run(void * cookie)
373  {
374  Sim_Agent_Graph * graph = static_cast<Sim_Agent_Graph*>(cookie);
375  // Lógica de ejecución de eventos
376  while (graph->get_status() != STOPPED)
377  {
378  while (graph->get_status() == SUSPENDED)
379  {
380  pthread_mutex_lock(&graph->suspend_mutex);
381  pthread_cond_wait(&graph->suspend_cond, &graph->suspend_mutex);
382  pthread_mutex_unlock(&graph->suspend_mutex);
383  }
384 
385  if (graph->events_heap.is_empty())
386  {
387  break;
388  }
389 
390  Sim_Event * next_event = graph->events_heap.getMin();
391 
392  graph->actual_time = next_event->actual_time;
393  next_event->execute_event(graph);
394 
395  //TODO Si ha pasado tiempo > callback_rate, ejecutar update_callback
396  //TODO Incluir evento en el heap
397 
398  if (next_event->to_be_destroyed)
399  {
400  delete next_event;
401  }
402  }
403  return NULL;
404  }
405 
406 
407  void run_static()
408  {
409  while (!events_heap.is_empty())
410  {
411  Sim_Event * next_event = events_heap.getMin();
412 
413  actual_time = next_event->actual_time;
414  next_event->execute_event(this);
415  if (next_event->to_be_destroyed)
416  {
417  delete next_event;
418  }
419  }
420  }
421 
422  };
423 }
424 #endif
Definition: tpl_concurrent_graph.H:22
Definition: tpl_sim_agent_graph.H:21
#define LINKNAME_TO_TYPE(type_name, link_name)
Definition: dlink.H:741
Definition: tpl_sim_agent_graph.H:30
const size_t & get_num_agents() const
Definition: tpl_sim_agent_graph.H:164
Definition: tpl_sim_agent_graph.H:28
Definition: tpl_sim_agent_graph.H:23
Definition: tpl_dynBinHeap.H:26
Definition: tpl_sim_agent_graph.H:59
Definition: tpl_agent_graph.H:22
Sim_Agent_Graph(const size_t &num_threads)
Definition: tpl_sim_agent_graph.H:233
Definition: tpl_sim_agent_graph.H:25

Leandro Rabindranath León