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* operator ->() const { return internal->value; }
00110
00112 bool valid() const
00113 { return internal->value != 0; }
00114
00136 void reset(T* ptr)
00137 {
00138 boost::intrusive_ptr<Internal> safe = this->internal;
00139 if (!safe)
00140 {
00141 internal = new Internal(ptr);
00142 return;
00143 }
00144
00145
00146 { os::MutexLock do_lock(safe->lock);
00147 if (safe->readers == 2)
00148 {
00149 delete safe->value;
00150 safe->value = ptr;
00151 return;
00152 }
00153 }
00154
00155
00156
00157
00158
00159
00160
00161 internal = new Internal(ptr);
00162 }
00163
00173 T* try_write_access()
00174 {
00175 boost::intrusive_ptr<Internal> safe = this->internal;
00176 if (!safe)
00177 return 0;
00178
00179 { os::MutexLock do_lock(safe->lock);
00180 if (safe->readers == 2)
00181 {
00182
00183 T* value = 0;
00184 std::swap(value, safe->value);
00185 return value;
00186 }
00187 else
00188 {
00189 return NULL;
00190 }
00191 }
00192 }
00193
00205 T* write_access()
00206 {
00207 boost::intrusive_ptr<Internal> safe = this->internal;
00208 if (!safe)
00209 return 0;
00210
00211 { os::MutexLock do_lock(safe->lock);
00212 if (safe->readers == 2)
00213 {
00214
00215 T* value = 0;
00216 std::swap(value, safe->value);
00217 return value;
00218 }
00219 else
00220 {
00221 return new T(*safe->value);
00222 }
00223 }
00224 }
00225 };
00226 }}
00227
00228 #endif
00229