SIMLIB/C++ 3.09
Loading...
Searching...
No Matches
barrier.cc
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2//! \file barrier.cc Barrier synchronization
3//
4// Copyright (c) 1991-2007 Petr Peringer
5//
6// This library is licensed under GNU Library GPL. See the file COPYING.
7//
8
9//
10// class Barrier implementation
11//
12// TODO add method to set activation order - FIFO/LIFO
13
14////////////////////////////////////////////////////////////////////////////
15// interface
16//
17
18#include "simlib.h"
19#include "internal.h"
20
21////////////////////////////////////////////////////////////////////////////
22// implementation
23//
24
25namespace simlib3 {
26
28
29////////////////////////////////////////////////////////////////////////////
30/// constructor
31//
32Barrier::Barrier(unsigned height):
33 waiting(0), n(0), maxn(height)
34{
35 Dprintf(("Barrier::Barrier()"));
36 Init();
37}
38
39////////////////////////////////////////////////////////////////////////////
40/// constructor with name parameter
41//
42Barrier::Barrier(const char *name, unsigned height):
43 waiting(0), n(0), maxn(height)
44{
45 Dprintf(("Barrier::Barrier(\"%s\")", name));
46 SetName(name);
47 Init();
48}
49
50
51////////////////////////////////////////////////////////////////////////////
52/// destructor
53//
55 Dprintf(("Barrier::~Barrier() // \"%s\" ", Name().c_str()));
56 delete[] waiting;
57}
58
59////////////////////////////////////////////////////////////////////////////
60/// enter the barrier
61//
62void Barrier::Enter(Entity * e) //TODO without parameter: use Current?
63{
64 Dprintf(("Barrier\"%s\".Enter(%s)", Name().c_str(), e->Name().c_str()));
65 if (n < maxn - 1) { // all waiting processes
66 waiting[n++] = e;
67 e->Passivate();
68 } else { // last process which breaks barrier
69 Break();
70 Current->Activate(); // re-activation of last process - FIFO order
71 }
72}
73
74////////////////////////////////////////////////////////////////////////////
75/// Wait or break the barrier
76/// returns: true for last process breaking the barrier, else false
77//
79{
80 Dprintf(("Barrier\"%s\".Wait() for %s", Name().c_str(), Current->Name().c_str()));
81 if (n < maxn - 1) { // all waiting processes
82 waiting[n++] = Current;
84 return false;
85 } else { // last process which breaks barrier
86 Break();
87 Current->Activate(Time); // re-activation of last process - FIFO order
88 return true;
89 }
90}
91
92////////////////////////////////////////////////////////////////////////////
93/// Activate all processes waiting on the barrier
94/// returns: number of activated entities
95/// Warning: can be called only by process not already waiting on barrier
96//
98 int ret = n;
99 if (n == 0) // nothing to do
100 return ret;
101 for (unsigned i = 0; i < n; i++) // FIFO order of activation
102 {
103 waiting[i]->Activate();
104 waiting[i] = 0;
105 }
106 n = 0;
107 return ret;
108}
109
110////////////////////////////////////////////////////////////////////////////
111/// Barrier initializtion
112//
114 Dprintf(("%s.Init()", Name().c_str()));
115 if (maxn < 1)
116 Error("Barrier size less than 1");
117 waiting = new Entity *[maxn]; // allocation maxn-1 ???
118// if(!waiting) SIMLIB_error(MemoryError); // if without exceptions
119 Clear();
120}
121
122////////////////////////////////////////////////////////////////////////////
123/// Change the height of barrier
124//
125void Barrier::ChangeHeight(unsigned new_height) {
126 Dprintf(("%s.ChangeHeight(%u)", Name().c_str(), new_height));
127 if (new_height < n || new_height < 1)
128 Error("Barrier height can not be changed");
129 Entity **new_w = new Entity *[new_height]; // allocation
130// if(!new_w) SIMLIB_error(MemoryError); // if compiled without exceptions
131 for (unsigned i = 0; i < n; i++) // copy
132 new_w[i] = waiting[i];
133 delete [] waiting; // free old array
134 waiting = new_w;
135 maxn = new_height; // new size
136 for (unsigned i = n; i < maxn; i++) // zero all non-used items
137 new_w[i] = 0;
138}
139
140////////////////////////////////////////////////////////////////////////////
141/// Barrier re-initializtion
142/// TODO: what to do with currently waiting passive processes?
143//
145 Dprintf(("%s.Clear()", Name().c_str()));
146 for (unsigned i = 0; i < maxn; i++)
147 waiting[i] = nullptr;
148 n = 0;
149}
150
151////////////////////////////////////////////////////////////////////////////
152/// Print barrier status
153//
154void Barrier::Output() const {
155 Print("Barrier: %s\n", Name().c_str());
156 for (unsigned i = 0; i < maxn; i++)
157 if (waiting[i])
158 Print("%3d: %s\n", i, waiting[i]->Name().c_str());
159 else
160 Print("%3d: empty\n", i);
161 Print("\n");
162}
163
164} // namespace
165
virtual bool Wait()
wait for barrier break (Current)
Definition: barrier.cc:78
unsigned n
current number of waiting entities
Definition: simlib.h:1779
void Init()
initialization
Definition: barrier.cc:113
void ChangeHeight(unsigned new_maxn)
change size
Definition: barrier.cc:125
virtual void Enter(Entity *e)
wait for barrier break TODO: remove/rename
Definition: barrier.cc:62
Entity ** waiting
array of waiting entities (fixed size)
Definition: simlib.h:1778
virtual int Break()
activate all waiting entities
Definition: barrier.cc:97
virtual void Output() const override
print status
Definition: barrier.cc:154
virtual ~Barrier()
destructor
Definition: barrier.cc:54
Barrier(unsigned N)
constructor
Definition: barrier.cc:32
void Clear()
initialization
Definition: barrier.cc:144
unsigned maxn
barrier height/size
Definition: simlib.h:1780
abstract base class for active entities (Process, Event) instances of derived classes provide Behavio...
Definition: simlib.h:375
void Activate()
activate now
Definition: simlib.h:408
virtual void Passivate()
deactivation
Definition: entity.cc:68
void SetName(const std::string &name)
assign the name
Definition: object.cc:125
virtual std::string Name() const
get object name
Definition: object.cc:134
Internal header file for SIMLIB/C++.
#define Dprintf(f)
Definition: internal.h:100
Implementation of class CalendarList interface is static - using global functions in SQS namespace.
Definition: algloop.cc:32
const double & Time
model time (is NOT the block)
Definition: run.cc:48
SIMLIB_IMPLEMENTATION
Definition: algloop.cc:34
void Error(const char *fmt,...)
print message and terminate program
Definition: print.cc:123
int Print(const char *fmt,...)
for Output methods, can be redirected
Definition: print.cc:92
Entity *const & Current
pointer to active (now running) entity
Definition: run.cc:54
Main SIMLIB/C++ interface.