00001
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
00034
00035 #ifndef GROOVX_NUB_REF_H_UTC20050626084019_DEFINED
00036 #define GROOVX_NUB_REF_H_UTC20050626084019_DEFINED
00037
00038 #include "nub/handle.h"
00039 #include "nub/object.h"
00040 #include "nub/weak_handle.h"
00041
00042 #include "rutz/fileposition.h"
00043 #include "rutz/stderror.h"
00044 #include "rutz/traits.h"
00045
00046 #include <typeinfo>
00047
00048 namespace nub
00049 {
00050 template <class T> class ref;
00051 template <class T> class soft_ref;
00052 template <class T> class floating_ref;
00053
00055 ref_vis get_default_ref_vis();
00056
00058 void set_default_ref_vis(ref_vis vis);
00059
00060 namespace detail
00061 {
00062 bool is_valid_uid(nub::uid id) throw();
00063 nub::object* get_checked_item(nub::uid id);
00064
00065 void insert_item(nub::object* obj, ref_vis vis);
00066
00067 template <class T>
00068 inline T* get_casted_item(nub::uid id)
00069 {
00070 nub::object* obj = get_checked_item(id);
00071 T* t = dynamic_cast<T*>(obj);
00072 if (t == 0)
00073 rutz::throw_bad_cast(typeid(T), typeid(nub::object), SRC_POS);
00074 return t;
00075 }
00076
00077 template <>
00078 inline nub::object* get_casted_item<nub::object>(nub::uid id)
00079 { return get_checked_item(id); }
00080
00082 template <class T>
00083 struct default_unref_policy
00084 {
00085 static void unref(T* t) throw() { t->decr_ref_count(); }
00086 };
00087
00089 template <class T>
00090 struct no_delete_unref_policy
00091 {
00092 static void unref(T* t) throw() { t->decr_ref_count_no_delete(); }
00093 };
00094
00095 }
00096
00097 }
00098
00099 namespace rutz
00100 {
00102 template <class T>
00103 struct type_traits<nub::ref<T> >
00104 {
00105 typedef T pointee_t;
00106 };
00107
00109 template <class T>
00110 struct type_traits<nub::soft_ref<T> >
00111 {
00112 typedef T pointee_t;
00113 };
00114 }
00115
00116
00117
00118
00120
00131
00132
00133 template <class T>
00134 class nub::ref
00135 {
00136 private:
00137
00138 typedef nub::detail::handle<T, nub::detail::default_unref_policy<T> >
00139 handle;
00140
00141 handle m_handle;
00142
00143 public:
00144
00145
00146 explicit ref(nub::uid i)
00147 : m_handle(detail::get_casted_item<T>(i)) {}
00148
00149 explicit ref(T* ptr, ref_vis vis = DEFAULT) :
00150 m_handle(ptr)
00151 {
00152 detail::insert_item(ptr, vis);
00153 }
00154
00155 template <class U>
00156 ref(const ref<U>& other) : m_handle(other.get()) {}
00157
00158
00159 template <class U>
00160 ref(const soft_ref<U>& other);
00161
00163
00166 void reset(T* p) { *this = ref(p); }
00167
00168 T* operator->() const throw() { return get(); }
00169 T& operator*() const throw() { return *(get()); }
00170
00171 T* get() const throw() { return m_handle.get(); }
00172
00173 bool operator==(const ref& other) const throw()
00174 { return m_handle == other.m_handle; }
00175
00176 bool operator!=(const ref& other) const throw()
00177 { return !(operator==(other)); }
00178
00179 nub::uid id() const throw()
00180 { return get()->id(); }
00181
00183
00184 bool operator<(const ref& other) const throw()
00185 { return get() < other.get(); }
00186 };
00187
00188 template <class To, class Fr>
00189 nub::ref<To> dyn_cast(nub::ref<Fr> p)
00190 {
00191 Fr* f = p.get();
00192 To* t = dynamic_cast<To*>(f);
00193 if (t == 0)
00194 rutz::throw_bad_cast(typeid(To), typeid(Fr), SRC_POS);
00195 return nub::ref<To>(t);
00196 }
00197
00198 template <class To, class Fr>
00199 void dyn_cast_to_from(nub::ref<To>& dest, nub::ref<Fr> p)
00200 {
00201 dest = dyn_cast<To, Fr>(p);
00202 }
00203
00204
00205
00206 template <class To, class Fr>
00207 nub::ref<To> dynCast(nub::ref<Fr> p)
00208 { return dyn_cast<To, Fr>(p); }
00209
00210 template <class To, class Fr>
00211 void dynCastToFrom(nub::ref<To>& dest, nub::ref<Fr> p)
00212 { dyn_cast_to_from<To, Fr>(dest, p); }
00213
00214
00216
00228
00229
00230 template <class T>
00231 class nub::soft_ref
00232 {
00233 private:
00234 mutable detail::weak_handle<T> m_handle;
00235
00236 public:
00237 soft_ref() : m_handle(0, STRONG) {}
00238
00239 explicit soft_ref(nub::uid i, ref_type tp = STRONG)
00240 :
00241 m_handle(detail::is_valid_uid(i) ?
00242 detail::get_casted_item<T>(i) : 0,
00243 tp)
00244 {}
00245
00246 explicit soft_ref(T* master,
00247 ref_type tp = STRONG, ref_vis vis = DEFAULT)
00248 :
00249 m_handle(master,tp)
00250 {
00251 if (m_handle.is_valid())
00252 {
00253 detail::insert_item(m_handle.get(), vis);
00254 }
00255 }
00256
00257 template <class U>
00258 soft_ref(const soft_ref<U>& other) :
00259 m_handle(other.is_valid() ? other.get() : 0, STRONG) {}
00260
00261 template <class U>
00262 soft_ref(const ref<U>& other) : m_handle(other.get(), STRONG) {}
00263
00264
00265
00267
00270 void reset(T* p = 0) { *this = soft_ref(p); }
00271
00274 T* get() const { return m_handle.get(); }
00275
00276 T* operator->() const { return m_handle.get(); }
00277 T& operator*() const { return *(m_handle.get()); }
00278
00281 T* get_weak() const throw() { return m_handle.get_weak(); }
00282
00283 ref_type get_ref_type() const throw() { return m_handle.get_ref_type(); }
00284
00285 bool is_valid() const throw() { return m_handle.is_valid(); }
00286 bool is_invalid() const throw() { return !(is_valid()); }
00287
00288 bool operator==(const soft_ref& other) const throw()
00289 { return get_weak() == other.get_weak(); }
00290
00291 bool operator!=(const soft_ref& other) const throw()
00292 { return get_weak() != other.get_weak(); }
00293
00295 bool operator<(const soft_ref& other) const throw()
00296 { return get_weak() < other.get_weak(); }
00297
00298 nub::uid id() const throw()
00299 { return m_handle.is_valid() ? m_handle.get()->id() : 0; }
00300
00301
00302
00303 T* getWeak() const throw() { return this->get_weak(); }
00304 bool isValid() const throw() { return this->is_valid(); }
00305 bool isInvalid() const throw() { return this->is_invalid(); }
00306 };
00307
00308
00309
00310 template <class To, class Fr>
00311 inline nub::soft_ref<To> dyn_cast(nub::soft_ref<Fr> p)
00312 {
00313 if (p.is_valid())
00314 {
00315 Fr* f = p.get();
00316 To* t = dynamic_cast<To*>(f);
00317 if (t == 0)
00318 rutz::throw_bad_cast(typeid(To), typeid(Fr), SRC_POS);
00319 return nub::soft_ref<To>(t);
00320 }
00321 return nub::soft_ref<To>(p.id());
00322 }
00323
00324 template <class To, class Fr>
00325 inline void dyn_cast_to_from(nub::soft_ref<To>& dest,
00326 nub::soft_ref<Fr> p)
00327 {
00328 dest = dyn_cast<To, Fr>(p);
00329 }
00330
00331
00332 template <class To, class Fr>
00333 inline nub::soft_ref<To> dyn_cast_weak(nub::soft_ref<Fr> p)
00334 {
00335 if (p.is_valid())
00336 {
00337 Fr* f = p.get();
00338 To* t = dynamic_cast<To*>(f);
00339 if (t == 0)
00340 return nub::soft_ref<To>();
00341 return nub::soft_ref<To>(t);
00342 }
00343 return nub::soft_ref<To>(p.id());
00344 }
00345
00346 template <class To, class Fr>
00347 inline void dyn_cast_weak_to_from(nub::soft_ref<To>& dest,
00348 nub::soft_ref<Fr> p)
00349 {
00350 dest = dyn_cast<To, Fr>(p);
00351 }
00352
00353
00354 template <class To, class Fr>
00355 inline nub::soft_ref<To> dyn_cast_weak(nub::ref<Fr> p)
00356 {
00357 Fr* f = p.get();
00358 To* t = dynamic_cast<To*>(f);
00359 if (t == 0)
00360 return nub::soft_ref<To>();
00361 return nub::soft_ref<To>(t);
00362 }
00363
00364 template <class To, class Fr>
00365 inline void dyn_cast_weak_to_from(nub::soft_ref<To>& dest,
00366 nub::ref<Fr> p)
00367 {
00368 dest = dyn_cast<To, Fr>(p);
00369 }
00370
00371
00372
00373
00374 template <class To, class Fr>
00375 inline nub::soft_ref<To> dynCast(nub::soft_ref<Fr> p)
00376 { return dyn_cast<To, Fr>(p); }
00377
00378
00379 template <class To, class Fr>
00380 inline void dynCastToFrom(nub::soft_ref<To>& dest,
00381 nub::soft_ref<Fr> p)
00382 { dyn_cast_to_from<To, Fr>(dest, p); }
00383
00384
00385 template <class To, class Fr>
00386 inline nub::soft_ref<To> dynCastWeak(nub::soft_ref<Fr> p)
00387 { return dyn_cast_weak<To, Fr>(p); }
00388
00389
00390 template <class To, class Fr>
00391 inline void dynCastWeakToFrom(nub::soft_ref<To>& dest,
00392 nub::soft_ref<Fr> p)
00393 { dyn_cast_weak_to_from<To, Fr>(dest, p); }
00394
00395
00396 template <class To, class Fr>
00397 inline nub::soft_ref<To> dynCastWeak(nub::ref<Fr> p)
00398 { return dyn_cast_weak<To, Fr>(p); }
00399
00400
00401 template <class To, class Fr>
00402 inline void dynCastWeakToFrom(nub::soft_ref<To>& dest,
00403 nub::ref<Fr> p)
00404 { dyn_cast_weak_to_from<To, Fr>(dest, p); }
00405
00406
00408
00418
00419
00420 template <class T>
00421 class nub::floating_ref
00422 {
00423 private:
00424
00425 typedef nub::detail::handle<T, nub::detail::no_delete_unref_policy<T> >
00426 handle;
00427
00428 handle m_handle;
00429
00430 floating_ref(const floating_ref&);
00431 floating_ref& operator=(const floating_ref&);
00432
00433 public:
00434
00435
00436 explicit floating_ref(T* ptr) : m_handle(ptr) {}
00437
00438 T* operator->() const throw() { return get(); }
00439 T& operator*() const throw() { return *(get()); }
00440
00441 T* get() const throw() { return m_handle.get(); }
00442 };
00443
00444
00445
00446
00448
00449
00450
00452
00453 template <class T>
00454 template <class U>
00455 inline nub::ref<T>::ref(const soft_ref<U>& other) :
00456 m_handle(other.get())
00457 {}
00458
00459 static const char __attribute__((used)) vcid_groovx_nub_ref_h_utc20050626084019[] = "$Id: ref.h 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00460 #endif // !GROOVX_NUB_REF_H_UTC20050626084019_DEFINED