Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef RTT_READ_WRITE_POINTER_HPP
00040 #define RTT_READ_WRITE_POINTER_HPP
00041
00042 #include <boost/intrusive_ptr.hpp>
00043 #include <boost/call_traits.hpp>
00044
00045 #include "../os/Mutex.hpp"
00046 #include "../os/MutexLock.hpp"
00047
00048 namespace RTT
00049 { namespace extras {
00050
00051 template<typename T>
00052 struct ROPtrInternal
00053 {
00054 os::Mutex lock;
00055 T* value;
00056 size_t readers;
00057
00058 ROPtrInternal(T* value)
00059 : value(value), readers(0) {}
00060 ~ROPtrInternal() { delete value; }
00061
00062 void ref()
00063 { os::MutexLock do_lock(lock);
00064 ++readers;
00065 }
00066 bool deref()
00067 { os::MutexLock do_lock(lock);
00068 return (--readers) != 0;
00069 }
00070 };
00071
00072 template<typename T>
00073 void intrusive_ptr_add_ref(ROPtrInternal<T>* data)
00074 {
00075 data->ref();
00076 }
00077 template<typename T>
00078 void intrusive_ptr_release(ROPtrInternal<T>* data)
00079 {
00080 if (!data->deref())
00081 delete data;
00082 }
00083
00097 template<typename T>
00098 class ReadOnlyPointer
00099 {
00100 typedef ROPtrInternal<T> Internal;
00101 boost::intrusive_ptr<Internal> internal;
00102 typedef boost::call_traits<T> traits;
00103
00104 public:
00105 ReadOnlyPointer(T* ptr = 0)
00106 : internal(new Internal(ptr)) {}
00107
00108 typename traits::const_reference operator *() const { return *(internal->value); }
00109 T const* operator ->() const { return internal->value; }
00110
00112 bool valid() const
00113 { return internal->value != 0; }
00114
00115 T const* get() const
00116 {
00117 return internal->value;
00118 }
00119
00141 void reset(T* ptr)
00142 {
00143 boost::intrusive_ptr<Internal> safe = this->internal;
00144 if (!safe)
00145 {
00146 internal = new Internal(ptr);
00147 return;
00148 }
00149
00150 if (safe->value == ptr)
00151 return;
00152
00153 { os::MutexLock do_lock(safe->lock);
00154 if (safe->readers == 2)
00155 {
00156 delete safe->value;
00157 safe->value = ptr;
00158 return;
00159 }
00160 }
00161
00162
00163
00164
00165
00166
00167
00168 internal = new Internal(ptr);
00169 }
00170
00180 T* try_write_access()
00181 {
00182 boost::intrusive_ptr<Internal> safe = this->internal;
00183 if (!safe)
00184 return 0;
00185
00186 { os::MutexLock do_lock(safe->lock);
00187 if (safe->readers == 2)
00188 {
00189
00190 T* value = 0;
00191 std::swap(value, safe->value);
00192 return value;
00193 }
00194 else
00195 {
00196 return NULL;
00197 }
00198 }
00199 }
00200
00212 T* write_access()
00213 {
00214 boost::intrusive_ptr<Internal> safe = this->internal;
00215 if (!safe)
00216 return 0;
00217
00218 { os::MutexLock do_lock(safe->lock);
00219 if (safe->readers == 2)
00220 {
00221
00222 T* value = 0;
00223 std::swap(value, safe->value);
00224 return value;
00225 }
00226 else
00227 {
00228 return new T(*safe->value);
00229 }
00230 }
00231 }
00232 };
00233 }}
00234
00235 #endif
00236