Orocos Real-Time Toolkit  2.9.0
ReadOnlyPointer.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Thu Oct 22 11:59:08 CEST 2009 ReadOnlyPointer.hpp
3 
4  ReadOnlyPointer.hpp - description
5  -------------------
6  begin : Thu October 22 2009
7  copyright : (C) 2009 Sylvain Joyeux
8  email : Sylvain Joyeux <sylvain.joyeux@m4x.org>
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 #ifndef RTT_READ_WRITE_POINTER_HPP
40 #define RTT_READ_WRITE_POINTER_HPP
41 
42 #include <boost/intrusive_ptr.hpp>
43 #include <boost/call_traits.hpp>
44 
45 #include "../os/Mutex.hpp"
46 #include "../os/MutexLock.hpp"
47 
48 namespace RTT
49 { namespace extras {
50 
51  template<typename T>
53  {
55  T* value;
56  size_t readers;
57 
58  ROPtrInternal(T* value)
59  : value(value), readers(0) {}
60  ~ROPtrInternal() { delete value; }
61 
62  void ref()
63  { os::MutexLock do_lock(lock);
64  ++readers;
65  }
66  bool deref()
67  { os::MutexLock do_lock(lock);
68  return (--readers) != 0;
69  }
70  };
71 
72  template<typename T>
74  {
75  data->ref();
76  }
77  template<typename T>
79  {
80  if (!data->deref())
81  delete data;
82  }
83 
97  template<typename T>
99  {
100  typedef ROPtrInternal<T> Internal;
101  boost::intrusive_ptr<Internal> internal;
102  typedef boost::call_traits<T> traits;
103 
104  public:
105  ReadOnlyPointer(T* ptr = 0)
106  : internal(new Internal(ptr)) {}
107 
108  typename traits::const_reference operator *() const { return *(internal->value); }
109  T const* operator ->() const { return internal->value; }
110 
112  bool valid() const
113  { return internal->value != 0; }
114 
115  T const* get() const
116  {
117  return internal->value;
118  }
119 
141  void reset(T* ptr)
142  {
143  boost::intrusive_ptr<Internal> safe = this->internal;
144  if (!safe)
145  {
146  internal = new Internal(ptr);
147  return;
148  }
149 
150  if (safe->value == ptr)
151  return;
152 
153  { os::MutexLock do_lock(safe->lock);
154  if (safe->readers == 2) // we are sole owner
155  {
156  delete safe->value;
157  safe->value = ptr;
158  return;
159  }
160  }
161 
162  // We must *not* change 'internal' while safe->lock is taken. The
163  // above block returns in case we don't need to reallocate a new
164  // Internal structure.
165  //
166  // In other words, if we are here, it is because we *need* to
167  // reallocate.
168  internal = new Internal(ptr);
169  }
170 
181  {
182  boost::intrusive_ptr<Internal> safe = this->internal;
183  if (!safe)
184  return 0;
185 
186  { os::MutexLock do_lock(safe->lock);
187  if (safe->readers == 2)
188  { // we're the only owner (don't forget +safe+ above).
189  // Just promote the current copy
190  T* value = 0;
191  std::swap(value, safe->value);
192  return value;
193  }
194  else
195  { // there are other owners
196  return NULL;
197  }
198  }
199  }
200 
213  {
214  boost::intrusive_ptr<Internal> safe = this->internal;
215  if (!safe)
216  return 0;
217 
218  { os::MutexLock do_lock(safe->lock);
219  if (safe->readers == 2)
220  { // we're the only owner (don't forget +safe+ above).
221  // Just promote the current copy
222  T* value = 0;
223  std::swap(value, safe->value);
224  return value;
225  }
226  else
227  { // there are other owners, do a copy
228  return new T(*safe->value);
229  }
230  }
231  }
232  };
233 }}
234 
235 #endif
236 
void intrusive_ptr_add_ref(ROPtrInternal< T > *data)
bool valid() const
True if this refers to a non-NULL pointer.
T * write_access()
Gets write access to the pointed-to object.
T * try_write_access()
Gets write access to the pointed-to object if it does not require any copying.
void reset(T *ptr)
Modifies the value referenced by this smart pointer.
MultiVector< S, D > operator*(const D d, const MultiVector< S, D > &v)
void intrusive_ptr_release(ROPtrInternal< T > *data)
Smart pointer that allows safe sharing of data between multiple threads.
An object oriented wrapper around a non recursive mutex.
Definition: Mutex.hpp:92
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
MutexLock is a scope based Monitor, protecting critical sections with a Mutex object through locking ...
Definition: MutexLock.hpp:51