cisst-saw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
osaTripleBuffer.h
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */
3 
4 /*
5 
6  Author(s): Martin Kelly, Anton Deguet
7  Created on: 2011-03-15
8 
9  (C) Copyright 2011 Johns Hopkins University (JHU), All Rights
10  Reserved.
11 
12 --- begin cisst license - do not edit ---
13 
14 This software is provided "as is" under an open source license, with
15 no warranty. The complete license can be found in license.txt and
16 http://www.cisst.org/cisst/license.txt.
17 
18 --- end cisst license ---
19 
20 */
21 
22 #include <cisstConfig.h> // to define CISST_OS and CISST_COMPILER
23 
24 #include <cisstCommon/cmnAssert.h>
26 
48 template <class _elementType>
50 {
51  friend class osaTripleBufferTest;
52 
53  typedef _elementType value_type;
54 
56 
57  typedef value_type * pointer;
58  typedef const value_type * const_pointer;
59  typedef value_type & reference;
60  typedef const value_type & const_reference;
61 
62  // did the buffer allocate memory or used existing pointers
63  bool OwnMemory;
64  pointer Memory;
65 
66  // circular buffer node
67  class Node {
68  public:
69  Node(const pointer data):
70  Pointer(data) {}
71  pointer Pointer;
72  Node * Next;
73  };
74 
75  typedef Node * NodePointer;
76 
77  // last write node (behaves like a head in our lifo circular buffer
78  volatile NodePointer LastWriteNode;
79  volatile NodePointer WriteNode;
80  volatile NodePointer ReadNode;
81 
82  // bool for debug
83  bool LastCompare;
84 
85  // to make sure the ReadNode is thread safe
86  osaMutex Mutex;
87 
88 
89 public:
92  inline osaTripleBuffer(void):
93  OwnMemory(true)
94  {
95  this->Memory = new value_type[3];
96  SetupNodes(this->Memory,
97  this->Memory + 1,
98  this->Memory + 2);
99  }
100 
104  inline osaTripleBuffer(const_reference initialValue):
105  OwnMemory(true),
106  Memory(0)
107  {
108  SetupNodes(new value_type(initialValue),
109  new value_type(initialValue),
110  new value_type(initialValue));
111  }
112 
117  inline osaTripleBuffer(pointer pointer1, pointer pointer2, pointer pointer3):
118  OwnMemory(false),
119  Memory(0)
120  {
121  SetupNodes(pointer1, pointer2, pointer3);
122  }
123 
126  inline void SetupNodes(pointer pointer1, pointer pointer2, pointer pointer3) {
127  CMN_ASSERT(pointer1);
128  CMN_ASSERT(pointer2);
129  CMN_ASSERT(pointer3);
130  this->ReadNode = 0;
131  this->WriteNode = 0;
132  this->LastWriteNode = new Node(pointer1);
133  this->LastWriteNode->Next = new Node(pointer2);
134  this->LastWriteNode->Next->Next = new Node(pointer3);
135  this->LastWriteNode->Next->Next->Next = this->LastWriteNode;
136  }
137 
140  inline ~osaTripleBuffer() {
141  // free memory if we own it
142  if (this->OwnMemory) {
143  // can be an array or three different pointers
144  if (this->Memory) {
145  delete[] this->Memory;
146  } else {
147  delete this->LastWriteNode->Next->Next->Pointer;
148  delete this->LastWriteNode->Next->Pointer;
149  delete this->LastWriteNode->Pointer;
150  }
151  }
152  // free nodes
153  delete this->LastWriteNode->Next->Next;
154  delete this->LastWriteNode->Next;
155  delete this->LastWriteNode;
156  }
157 
160  inline void Read(reference placeHolder) {
161  this->BeginRead();
162  placeHolder = *(ReadNode->Pointer);
163  this->EndRead();
164  }
165 
168  inline void Write(const_reference newValue) {
169  this->BeginWrite();
170  *(WriteNode->Pointer) = newValue;
171  this->EndWrite();
172  }
173 
178  inline const_pointer GetReadPointer(void) const {
179  return this->ReadNode->Pointer;
180  }
181 
186  inline pointer GetWritePointer(void) const {
187  return this->WriteNode->Pointer;
188  }
189 
192  inline void BeginRead(void) {
193  Mutex.Lock(); {
194  this->ReadNode = this->LastWriteNode;
195  } Mutex.Unlock();
196  }
197 
199  inline void EndRead(void) {
200  Mutex.Lock(); {
201  this->ReadNode = 0;
202  } Mutex.Unlock();
203  }
204 
205 
208  inline void BeginWrite(void) {
209  this->WriteNode = this->LastWriteNode->Next;
210  Mutex.Lock(); {
211  LastCompare = (this->WriteNode == this->ReadNode);
212  if (LastCompare) {
213  this->WriteNode = this->WriteNode->Next;
214  }
215  } Mutex.Unlock();
216  }
217 
218 
220  inline void EndWrite(void) {
221  this->LastWriteNode = this->WriteNode;
222  }
223 
224 
226  void ToStream(std::ostream & outputStream) const {
227  outputStream << "Node addresses from LastWriteNode: "
228  << this->LastWriteNode << "[" << this->LastWriteNode->Pointer << "] "
229  << this->LastWriteNode->Next << "[" << this->LastWriteNode->Next->Pointer << "] "
230  << this->LastWriteNode->Next->Next << "[" << this->LastWriteNode->Next->Next->Pointer << "]" << std::endl
231  << "LastCompare of read/write: " << ((this->LastCompare) ? "equal" : "different") << std::endl
232  << "ReadNode address: " << this->ReadNode << std::endl
233  << "WriteNode address: " << this->WriteNode << std::endl;
234  }
235 };
Assert macros definitions.
pointer GetWritePointer(void) const
Definition: osaTripleBuffer.h:186
const_pointer GetReadPointer(void) const
Definition: osaTripleBuffer.h:178
#define CMN_ASSERT(expr)
Definition: cmnAssert.h:90
Declaration of osaMutex.
Define a Mutex object.
Definition: osaMutex.h:48
void ToStream(std::ostream &outputStream) const
Definition: osaTripleBuffer.h:226
void Read(reference placeHolder)
Definition: osaTripleBuffer.h:160
void BeginWrite(void)
Definition: osaTripleBuffer.h:208
~osaTripleBuffer()
Definition: osaTripleBuffer.h:140
void Write(const_reference newValue)
Definition: osaTripleBuffer.h:168
void SetupNodes(pointer pointer1, pointer pointer2, pointer pointer3)
Definition: osaTripleBuffer.h:126
friend class osaTripleBufferTest
Definition: osaTripleBuffer.h:51
void BeginRead(void)
Definition: osaTripleBuffer.h:192
void Unlock(void)
void EndRead(void)
Definition: osaTripleBuffer.h:199
osaTripleBuffer(void)
Definition: osaTripleBuffer.h:92
osaTripleBuffer(pointer pointer1, pointer pointer2, pointer pointer3)
Definition: osaTripleBuffer.h:117
osaTripleBuffer(const_reference initialValue)
Definition: osaTripleBuffer.h:104
void EndWrite(void)
Definition: osaTripleBuffer.h:220
void Lock(void)
Definition: osaTripleBuffer.h:49