AERA
pipe.h
1 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
2 //_/_/
3 //_/_/ AERA
4 //_/_/ Autocatalytic Endogenous Reflective Architecture
5 //_/_/
6 //_/_/ Copyright (c) 2018-2025 Jeff Thompson
7 //_/_/ Copyright (c) 2018-2025 Kristinn R. Thorisson
8 //_/_/ Copyright (c) 2018-2025 Icelandic Institute for Intelligent Machines
9 //_/_/ http://www.iiim.is
10 //_/_/
11 //_/_/ Copyright (c) 2010-2012 Eric Nivel, Thor List
12 //_/_/ Center for Analysis and Design of Intelligent Agents
13 //_/_/ Reykjavik University, Menntavegur 1, 102 Reykjavik, Iceland
14 //_/_/ http://cadia.ru.is
15 //_/_/
16 //_/_/ Part of this software was developed by Eric Nivel
17 //_/_/ in the HUMANOBS EU research project, which included
18 //_/_/ the following parties:
19 //_/_/
20 //_/_/ Autonomous Systems Laboratory
21 //_/_/ Technical University of Madrid, Spain
22 //_/_/ http://www.aslab.org/
23 //_/_/
24 //_/_/ Communicative Machines
25 //_/_/ Edinburgh, United Kingdom
26 //_/_/ http://www.cmlabs.com/
27 //_/_/
28 //_/_/ Istituto Dalle Molle di Studi sull'Intelligenza Artificiale
29 //_/_/ University of Lugano and SUPSI, Switzerland
30 //_/_/ http://www.idsia.ch/
31 //_/_/
32 //_/_/ Institute of Cognitive Sciences and Technologies
33 //_/_/ Consiglio Nazionale delle Ricerche, Italy
34 //_/_/ http://www.istc.cnr.it/
35 //_/_/
36 //_/_/ Dipartimento di Ingegneria Informatica
37 //_/_/ University of Palermo, Italy
38 //_/_/ http://diid.unipa.it/roboticslab/
39 //_/_/
40 //_/_/
41 //_/_/ --- HUMANOBS Open-Source BSD License, with CADIA Clause v 1.0 ---
42 //_/_/
43 //_/_/ Redistribution and use in source and binary forms, with or without
44 //_/_/ modification, is permitted provided that the following conditions
45 //_/_/ are met:
46 //_/_/ - Redistributions of source code must retain the above copyright
47 //_/_/ and collaboration notice, this list of conditions and the
48 //_/_/ following disclaimer.
49 //_/_/ - Redistributions in binary form must reproduce the above copyright
50 //_/_/ notice, this list of conditions and the following disclaimer
51 //_/_/ in the documentation and/or other materials provided with
52 //_/_/ the distribution.
53 //_/_/
54 //_/_/ - Neither the name of its copyright holders nor the names of its
55 //_/_/ contributors may be used to endorse or promote products
56 //_/_/ derived from this software without specific prior
57 //_/_/ written permission.
58 //_/_/
59 //_/_/ - CADIA Clause: The license granted in and to the software
60 //_/_/ under this agreement is a limited-use license.
61 //_/_/ The software may not be used in furtherance of:
62 //_/_/ (i) intentionally causing bodily injury or severe emotional
63 //_/_/ distress to any person;
64 //_/_/ (ii) invading the personal privacy or violating the human
65 //_/_/ rights of any person; or
66 //_/_/ (iii) committing or preparing for any act of war.
67 //_/_/
68 //_/_/ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
69 //_/_/ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
70 //_/_/ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
71 //_/_/ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
72 //_/_/ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
73 //_/_/ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
74 //_/_/ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
75 //_/_/ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
76 //_/_/ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
77 //_/_/ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
78 //_/_/ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
79 //_/_/ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80 //_/_/ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
81 //_/_/ OF SUCH DAMAGE.
82 //_/_/
83 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
84 
85 #ifndef core_pipe_h
86 #define core_pipe_h
87 
88 #include "utils.h"
89 
90 
91 #define PIPE_1
92 
93 namespace core {
94 
95 // Pipes are thread safe, depending on their type:
96 // 11: 1 writer, 1 reader
97 // 1N: 1 writer, N readers
98 // N1: N writers, 1 reader
99 // NN: N writers, N readers
100 #ifdef PIPE_1
101 template<typename T, uint32 _S> class Pipe11 :
102  public Semaphore,
103  public CriticalSection {
104 private:
105  class Block {
106  public:
107  T buffer_[_S * sizeof(T)];
108  Block *next_;
109  Block(Block *prev) : next_(NULL) { if (prev) prev->next_ = this; }
110  ~Block() { if (next_) delete next_; }
111  };
112  int32 head_;
113  int32 tail_;
114  Block *first_;
115  Block *last_;
116  Block *spare_;
117 protected:
118  void _clear();
119  T _pop();
120 public:
121  Pipe11();
122  ~Pipe11();
123  void clear();
124  void push(T &t); // increases the size as necessary
125  T pop(); // decreases the size as necessary
126 };
127 
128 template<typename T, uint32 _S> class Pipe1N :
129  public Pipe11<T, _S> {
130 private:
131  CriticalSection popCS_;
132 public:
133  Pipe1N();
134  ~Pipe1N();
135  void clear();
136  T pop();
137 };
138 
139 template<typename T, uint32 _S> class PipeN1 :
140  public Pipe11<T, _S> {
141 private:
142  CriticalSection pushCS_;
143 public:
144  PipeN1();
145  ~PipeN1();
146  void clear();
147  void push(T &t);
148 };
149 
150 template<typename T, uint32 _S> class PipeNN :
151  public Pipe11<T, _S> {
152 private:
153  CriticalSection pushCS_;
154  CriticalSection popCS_;
155 public:
156  PipeNN();
157  ~PipeNN();
158  void clear();
159  void push(T &t);
160 
168  T pop(bool waitForItem = true);
169 };
170 #elif defined PIPE_2
171 template<typename T, uint32 _S, class Pipe> class Push1;
172 template<typename T, uint32 _S, class Pipe> class PushN;
173 template<typename T, uint32 _S, class Pipe> class Pop1;
174 template<typename T, uint32 _S, class Pipe> class PopN;
175 
176 // a Pipe<T,_S> is a linked list of blocks containing _S objects of type T
177 // push() adds an object at the tail of the last block and moves the tail forward; when the tail reaches the end of the last block, a new block is appended to the list
178 // pop() moves the head forward and returns the object at this location; when the head reaches the end of the first block, this block is deallocated
179 // Synchronization between readers and writers is lock-free under no contention (reqCount), and uses a lock (Semaphore::) under contention
180 // single writer pipes can use an int32 tail, whereas multiple writer versions require int32 volatile tail; idem for readers
181 // The Head and Tail argument is meant to allow the parameterizing of heads and tails
182 // Push and Pop are functors tailored to the multiplicity of resp. the read and write threads
183 // P is the actual pipe class (e.g. Pipe11, etc.)
184 template<typename T, uint32 _S, typename Head, typename Tail, class P, template<typename, uint32, class> class Push, template<typename, uint32, class> class Pop> class Pipe :
185  public Semaphore {
186  template<typename T, uint32 _S, class Pipe> friend class Push1;
187  template<typename T, uint32 _S, class Pipe> friend class PushN;
188  template<typename T, uint32 _S, class Pipe> friend class Pop1;
189  template<typename T, uint32 _S, class Pipe> friend class PopN;
190 protected:
191  class Block {
192  public:
193  T buffer_[_S];
194  Block *next_;
195  Block(Block *prev) : next_(NULL) { if (prev) prev->next_ = this; }
196  ~Block() { if (next_) delete next_; }
197  };
198  Block *first_;
199  Block *last_;
200  Block *spare_; // pipes always retain a spare block: if a block is to be deallocated and there is no spare, it becomes the spare
201 
202  Head head_; // starts at -1
203  Tail tail_; // starts at 0
204  int32 volatile waitingList_; // amount of readers that have to wait, negative value indicate free lunch
205 
206  Push<T, _S, P> *_push;
207  Pop<T, _S, P> *_pop;
208 
209  void shrink(); // deallocates the first block when head_ reaches its end
210  void grow(); // allocate a new last block when tail_ reaches its end
211 
212  Pipe();
213 public:
214  ~Pipe();
215  void push(T &t);
216  T pop();
217 };
218 
219 template<class Pipe> class PipeFunctor {
220 protected:
221  Pipe &const pipe;
222  PipeFunctor(Pipe &p);
223 };
224 
225 template<typename T, uint32 _S, class Pipe> class Push1 :
226  public PipeFunctor<Pipe> {
227 public:
228  Push1(Pipe &p);
229  void operator ()(T &t);
230 };
231 
232 template<typename T, uint32 _S, class Pipe> class PushN :
233  public PipeFunctor<Pipe>,
234  public Semaphore {
235 public:
236  PushN(Pipe &p);
237  void operator ()(T &t);
238 };
239 
240 template<typename T, uint32 _S, class Pipe> class Pop1 :
241  public PipeFunctor<Pipe> {
242 public:
243  Pop1(Pipe &p);
244  T operator ()();
245 };
246 
247 template<typename T, uint32 _S, class Pipe> class PopN :
248  public PipeFunctor<Pipe>,
249  public Semaphore {
250 public:
251  PopN(Pipe &p);
252  T operator ()();
253 };
254 
255 template<typename T, uint32 S> class Pipe11 :
256  public Pipe<T, S, int32, int32, Pipe11<T, S>, Push1, Pop1> {
257 public:
258  Pipe11();
259  ~Pipe11();
260 };
261 
262 template<typename T, uint32 S> class Pipe1N :
263  public Pipe<T, S, int32, int32 volatile, Pipe1N<T, S>, Push1, PopN> {
264 public:
265  Pipe1N();
266  ~Pipe1N();
267 };
268 
269 template<typename T, uint32 S> class PipeN1 :
270  public Pipe<T, S, int32 volatile, int32, PipeN1<T, S>, PushN, Pop1> {
271 public:
272  PipeN1();
273  ~PipeN1();
274 };
275 
276 template<typename T, uint32 S> class PipeNN :
277  public Pipe<T, S, int32 volatile, int32 volatile, PipeNN<T, S>, PushN, PopN> {
278 public:
279  PipeNN();
280  ~PipeNN();
281 };
282 #endif
283 }
284 
285 
286 #include "pipe.tpl.cpp"
287 
288 
289 #endif
core::PipeNN::pop
T pop(bool waitForItem=true)
core::PipeNN
Definition: pipe.h:151
core::PipeN1
Definition: pipe.h:140
core::Pipe11
Definition: pipe.h:103
core::CriticalSection
Definition: submodules/CoreLibrary/CoreLibrary/utils.h:233
core::Semaphore
Definition: submodules/CoreLibrary/CoreLibrary/utils.h:208
core::Pipe1N
Definition: pipe.h:129