diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2010-08-16 11:45:23 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2010-08-16 11:45:23 +0200 |
commit | c56f32eb5e0b88ef8297a691f5286ba4aa4aa8b4 (patch) | |
tree | b6978e5a2e90839f1b0f3faead5448b926b1b010 | |
parent | b9376a8bd73d12c868dafa2d1f686058a77d35be (diff) |
Add pointer guard for naked pointer
-rw-r--r-- | odb/database.txx | 2 | ||||
-rw-r--r-- | odb/pointer-traits.hxx | 41 | ||||
-rw-r--r-- | odb/result.hxx | 25 | ||||
-rw-r--r-- | odb/traits.hxx | 12 |
4 files changed, 69 insertions, 11 deletions
diff --git a/odb/database.txx b/odb/database.txx index a120afa..bec3234 100644 --- a/odb/database.txx +++ b/odb/database.txx @@ -32,7 +32,7 @@ namespace odb typename traits::pointer_type r (find<T> (id)); - if (traits::pointer_ops::null_ptr (r)) + if (traits::pointer_traits::null_ptr (r)) throw object_not_persistent (); return r; diff --git a/odb/pointer-traits.hxx b/odb/pointer-traits.hxx index a715a9d..26f8b90 100644 --- a/odb/pointer-traits.hxx +++ b/odb/pointer-traits.hxx @@ -16,6 +16,24 @@ namespace odb template <typename P> class pointer_traits; + // No-op pointer guard for smart pointers. + // + template <typename P> + class nop_guard + { + public: + nop_guard () {} + + explicit + nop_guard (P) {} + + void + release () {} + + void + reset (P) {} + }; + // Default implementation that should work for any sensible smart // pointer with one template argument (object type). The only // assumptions that we make are the availability of operator-> and @@ -28,6 +46,7 @@ namespace odb public: typedef T type; typedef P<T> pointer; + typedef nop_guard<pointer> guard; // Return underlying pointer, including NULL. // @@ -77,12 +96,33 @@ namespace odb // Specialization for naked pointer. // + template <typename P> + class nptr_guard + { + public: + ~nptr_guard () {delete p_;} + nptr_guard (): p_ (0) {} + + explicit + nptr_guard (P p): p_ (p) {} + + void + release () {p_ = 0;} + + void + reset (P p) {delete p_; p_ = p;} + + private: + P p_; + }; + template <typename T> class pointer_traits<T*> { public: typedef T type; typedef T* pointer; + typedef nptr_guard<pointer> guard; static type* get_ptr (pointer p) @@ -126,6 +166,7 @@ namespace odb public: typedef T type; typedef odb::shared_ptr<T> pointer; + typedef nop_guard<pointer> guard; static type* get_ptr (const pointer& p) diff --git a/odb/result.hxx b/odb/result.hxx index 87374e5..0323b66 100644 --- a/odb/result.hxx +++ b/odb/result.hxx @@ -32,12 +32,19 @@ namespace odb friend class result<T>; friend class result_iterator<T>; - typename object_traits<T>::pointer_type - current (bool /*release*/) + typedef object_traits<T> traits; + typedef typename traits::pointer_type pointer_type; + typedef typename traits::pointer_traits pointer_traits; + + pointer_type + current (bool release) { - if (object_traits<T>::pointer_ops::null_ptr (current_) && !end_) + if (pointer_traits::null_ptr (current_) && !end_) current (); + if (release) + guard_.release (); + return current_; } @@ -58,8 +65,18 @@ namespace odb next () = 0; protected: + void + current (pointer_type p) + { + current_ = p; + guard_.reset (current_); + } + bool end_; - typename object_traits<T>::pointer_type current_; + + private: + pointer_type current_; + typename pointer_traits::guard guard_; }; template <typename T> diff --git a/odb/traits.hxx b/odb/traits.hxx index d38ee41..e5c9eed 100644 --- a/odb/traits.hxx +++ b/odb/traits.hxx @@ -67,16 +67,16 @@ namespace odb create () { void* v (pointer_traits<P>::allocate (sizeof (object_type))); - guard g (v); + mem_guard g (v); P p (new (v) object_type); g.release (); return p; } private: - struct guard + struct mem_guard { - guard (void* p): p_ (p) {} - ~guard () {if (p_) pointer_traits<P>::free (p_);} + mem_guard (void* p): p_ (p) {} + ~mem_guard () {if (p_) pointer_traits<P>::free (p_);} void release () {p_ = 0;} void* p_; }; @@ -86,8 +86,8 @@ namespace odb struct object_traits: access::object_traits<T> { typedef - pointer_traits<typename access::object_traits<T>::pointer_type> - pointer_ops; + odb::pointer_traits<typename access::object_traits<T>::pointer_type> + pointer_traits; }; } |