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
00151 { os::MutexLock do_lock(safe->lock);
00152 if (safe->readers == 2)
00153 {
00154 delete safe->value;
00155 safe->value = ptr;
00156 return;
00157 }
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 internal = new Internal(ptr);
00167 }
00168
00178 T* try_write_access()
00179 {
00180 boost::intrusive_ptr<Internal> safe = this->internal;
00181 if (!safe)
00182 return 0;
00183
00184 { os::MutexLock do_lock(safe->lock);
00185 if (safe->readers == 2)
00186 {
00187
00188 T* value = 0;
00189 std::swap(value, safe->value);
00190 return value;
00191 }
00192 else
00193 {
00194 return NULL;
00195 }
00196 }
00197 }
00198
00210 T* write_access()
00211 {
00212 boost::intrusive_ptr<Internal> safe = this->internal;
00213 if (!safe)
00214 return 0;
00215
00216 { os::MutexLock do_lock(safe->lock);
00217 if (safe->readers == 2)
00218 {
00219
00220 T* value = 0;
00221 std::swap(value, safe->value);
00222 return value;
00223 }
00224 else
00225 {
00226 return new T(*safe->value);
00227 }
00228 }
00229 }
00230 };
00231 }}
00232
00233 #endif
00234