aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-12-09 10:36:15 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-12-09 10:36:15 +0200
commitec355c48c49074bebeb597f6e5dcedfeb9d52fae (patch)
tree9adb18bffe27c6d0bce53c7e6bad6be583dc59ee
parentd2b7cfe47694cef008949255426cc57ab9a8e18a (diff)
Add lazy pointer support
Built-in support is provided for raw, auto, and tr1 shared/weak pointers. New test: common/lazy-ptr.
-rw-r--r--odb/forward.hxx3
-rw-r--r--odb/lazy-pointer-traits.hxx69
-rw-r--r--odb/lazy-ptr-impl.hxx149
-rw-r--r--odb/lazy-ptr-impl.ixx268
-rw-r--r--odb/lazy-ptr-impl.txx51
-rw-r--r--odb/lazy-ptr.hxx198
-rw-r--r--odb/lazy-ptr.ixx471
-rw-r--r--odb/lazy-ptr.txx30
-rw-r--r--odb/pointer-traits.hxx2
-rw-r--r--odb/tr1-pointer-traits.hxx12
-rw-r--r--odb/tr1/lazy-pointer-traits.hxx63
-rw-r--r--odb/tr1/lazy-ptr.hxx239
-rw-r--r--odb/tr1/lazy-ptr.ixx649
-rw-r--r--odb/tr1/lazy-ptr.txx59
14 files changed, 2260 insertions, 3 deletions
diff --git a/odb/forward.hxx b/odb/forward.hxx
index 30d9193..6c5d875 100644
--- a/odb/forward.hxx
+++ b/odb/forward.hxx
@@ -35,6 +35,9 @@ namespace odb
class container_traits;
};
+ template <typename T>
+ struct object_traits;
+
namespace details
{
template <typename X>
diff --git a/odb/lazy-pointer-traits.hxx b/odb/lazy-pointer-traits.hxx
new file mode 100644
index 0000000..599b051
--- /dev/null
+++ b/odb/lazy-pointer-traits.hxx
@@ -0,0 +1,69 @@
+// file : odb/lazy-pointer-traits.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_LAZY_POINTER_TRAITS_HXX
+#define ODB_LAZY_POINTER_TRAITS_HXX
+
+#include <odb/pre.hxx>
+
+#include <odb/pointer-traits.hxx>
+#include <odb/lazy-ptr.hxx>
+
+namespace odb
+{
+ template <typename T>
+ class pointer_traits< lazy_ptr<T> >
+ {
+ public:
+ static pointer_kind const kind = pk_naked;
+ static bool const lazy = true;
+
+ typedef T element_type;
+ typedef lazy_ptr<element_type> pointer_type;
+ typedef element_type* eager_pointer_type;
+
+ static bool
+ null_ptr (const pointer_type& p)
+ {
+ return !p;
+ }
+
+ template <class O /* = T */>
+ static typename object_traits<O>::id_type
+ object_id (const pointer_type& p)
+ {
+ return p.object_id<O> ();
+ }
+ };
+
+ template <typename T>
+ class pointer_traits< lazy_auto_ptr<T> >
+ {
+ public:
+ static pointer_kind const kind = pk_unique;
+ static bool const lazy = true;
+
+ typedef T element_type;
+ typedef lazy_auto_ptr<element_type> pointer_type;
+ typedef std::auto_ptr<element_type> eager_pointer_type;
+
+ static bool
+ null_ptr (const pointer_type& p)
+ {
+ return !p;
+ }
+
+ template <class O /* = T */>
+ static typename object_traits<O>::id_type
+ object_id (const pointer_type& p)
+ {
+ return p.object_id<O> ();
+ }
+ };
+}
+
+#include <odb/post.hxx>
+
+#endif // ODB_LAZY_POINTER_TRAITS_HXX
diff --git a/odb/lazy-ptr-impl.hxx b/odb/lazy-ptr-impl.hxx
new file mode 100644
index 0000000..b480da5
--- /dev/null
+++ b/odb/lazy-ptr-impl.hxx
@@ -0,0 +1,149 @@
+// file : odb/lazy-ptr-impl.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_LAZY_PTR_IMPL_HXX
+#define ODB_LAZY_PTR_IMPL_HXX
+
+#include <odb/pre.hxx>
+
+#include <odb/forward.hxx> // odb::database
+#include <odb/traits.hxx>
+
+#include <odb/details/export.hxx>
+
+namespace odb
+{
+ struct LIBODB_EXPORT lazy_ptr_impl_ref
+ {
+ void* id_;
+ database* db_;
+ void (*free_) (void*);
+ void* (*copy_) (const void*);
+ };
+
+ class LIBODB_EXPORT lazy_ptr_base
+ {
+ public:
+ typedef odb::database database_type;
+
+ ~lazy_ptr_base ();
+ lazy_ptr_base ();
+ lazy_ptr_base (const lazy_ptr_base&);
+ lazy_ptr_base (const lazy_ptr_impl_ref&);
+
+ lazy_ptr_base&
+ operator= (const lazy_ptr_base&);
+
+ lazy_ptr_base&
+ operator= (const lazy_ptr_impl_ref&);
+
+ // Reset both the id and database.
+ //
+ void
+ reset ();
+
+ // Reset the id and set the database to the new value.
+ //
+ void
+ reset (database_type&);
+
+ // Reset the id.
+ //
+ void
+ reset_id ();
+
+ void
+ swap (lazy_ptr_base&);
+
+ database_type*
+ database () const;
+
+ typedef void* lazy_ptr_base::*unspecified_bool_type;
+ operator unspecified_bool_type () const
+ {
+ return id_ != 0 ? &lazy_ptr_base::id_ : 0;
+ }
+
+ operator lazy_ptr_impl_ref ();
+
+ protected:
+ typedef void (*free_func) (void*);
+ typedef void* (*copy_func) (const void*);
+
+ // Makes a copy of id.
+ //
+ void
+ reset_ (database_type*, const void* id, free_func, copy_func);
+
+ template <typename T>
+ static void
+ free (void*);
+
+ template <typename T>
+ static void*
+ copy (const void*);
+
+ protected:
+ void* id_;
+ database_type* db_;
+
+ private:
+ free_func free_;
+ copy_func copy_;
+ };
+
+ template <typename T>
+ class lazy_ptr_impl: public lazy_ptr_base
+ {
+ public:
+ lazy_ptr_impl ();
+
+ template <typename ID>
+ lazy_ptr_impl (database_type&, const ID&);
+
+ lazy_ptr_impl (const lazy_ptr_impl&);
+
+ template <typename Y>
+ lazy_ptr_impl (const lazy_ptr_impl<Y>&);
+
+ lazy_ptr_impl (const lazy_ptr_impl_ref&);
+
+ lazy_ptr_impl&
+ operator= (const lazy_ptr_impl&);
+
+ template <typename Y>
+ lazy_ptr_impl&
+ operator= (const lazy_ptr_impl<Y>&);
+
+ lazy_ptr_impl&
+ operator= (const lazy_ptr_impl_ref&);
+
+ using lazy_ptr_base::reset;
+ using lazy_ptr_base::reset_id;
+
+ template <typename ID>
+ void
+ reset (database_type&, const ID&);
+
+ template <typename ID>
+ void
+ reset_id (const ID&);
+
+ template <typename O /* = T */>
+ typename object_traits<O>::pointer_type
+ load (bool reset_id);
+
+ template <typename O /* = T */>
+ typename object_traits<O>::id_type
+ object_id () const;
+ };
+}
+
+#include <odb/lazy-ptr-impl.ixx>
+#include <odb/lazy-ptr-impl.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_LAZY_PTR_IMPL_HXX
diff --git a/odb/lazy-ptr-impl.ixx b/odb/lazy-ptr-impl.ixx
new file mode 100644
index 0000000..8acd11c
--- /dev/null
+++ b/odb/lazy-ptr-impl.ixx
@@ -0,0 +1,268 @@
+// file : odb/lazy-ptr-impl.ixx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ //
+ // lazy_ptr_base
+ //
+
+ inline lazy_ptr_base::
+ lazy_ptr_base ()
+ : id_ (0), db_ (0)
+ {
+ }
+
+ inline lazy_ptr_base::
+ lazy_ptr_base (const lazy_ptr_base& r)
+ : id_ (0), db_ (r.db_), free_ (r.free_), copy_ (r.copy_)
+ {
+ if (r.id_)
+ id_ = copy_ (r.id_);
+ }
+
+ inline lazy_ptr_base::
+ lazy_ptr_base (const lazy_ptr_impl_ref& r)
+ : id_ (r.id_), db_ (r.db_), free_ (r.free_), copy_ (r.copy_)
+ {
+ }
+
+ inline lazy_ptr_base& lazy_ptr_base::
+ operator= (const lazy_ptr_base& r)
+ {
+ if (id_ != r.id_)
+ reset_ (r.db_, r.id_, r.free_, r.copy_);
+ else
+ db_ = r.db_;
+
+ return *this;
+ }
+
+ inline lazy_ptr_base& lazy_ptr_base::
+ operator= (const lazy_ptr_impl_ref& r)
+ {
+ if (id_ != r.id_)
+ {
+ reset_id ();
+ id_ = r.id_;
+ free_ = r.free_;
+ copy_ = r.copy_;
+ }
+
+ db_ = r.db_;
+ return *this;
+ }
+
+ inline lazy_ptr_base::
+ ~lazy_ptr_base ()
+ {
+ if (id_)
+ free_ (id_);
+ }
+
+ inline void lazy_ptr_base::
+ reset ()
+ {
+ reset_id ();
+ db_ = 0;
+ }
+
+ inline void lazy_ptr_base::
+ reset (database_type& db)
+ {
+ reset_id ();
+ db_ = &db;
+ }
+
+ inline void lazy_ptr_base::
+ reset_id ()
+ {
+ if (id_)
+ free_ (id_);
+
+ id_ = 0;
+ }
+
+ inline void lazy_ptr_base::
+ reset_ (database_type* db, const void* id, free_func free, copy_func copy)
+ {
+ void* idc (id ? copy (id) : 0);
+
+ if (id_)
+ free_ (id_);
+
+ free_ = free;
+ copy_ = copy;
+
+ id_ = idc;
+ db_ = db;
+ }
+
+ inline void lazy_ptr_base::
+ swap (lazy_ptr_base& r)
+ {
+ void* id (id_);
+ database_type* db (db_);
+ free_func f (free_);
+ copy_func c (copy_);
+
+ id_ = r.id_;
+ db_ = r.db_;
+ free_ = r.free_;
+ copy_ = r.copy_;
+
+ r.id_ = id;
+ r.db_ = db;
+ r.free_ = f;
+ r.copy_ = c;
+ }
+
+ inline lazy_ptr_base::database_type* lazy_ptr_base::
+ database () const
+ {
+ return db_;
+ }
+
+ inline lazy_ptr_base::
+ operator lazy_ptr_impl_ref ()
+ {
+ lazy_ptr_impl_ref r;
+ r.id_ = id_;
+ r.db_ = db_;
+ r.free_ = free_;
+ r.copy_ = copy_;
+ id_ = 0;
+ db_ = 0;
+ return r;
+ }
+
+ //
+ // lazy_ptr_impl
+ //
+
+ template <typename T>
+ inline lazy_ptr_impl<T>::
+ lazy_ptr_impl ()
+ {
+ }
+
+ template <typename T>
+ template <typename ID>
+ inline lazy_ptr_impl<T>::
+ lazy_ptr_impl (database_type& db, const ID& id)
+ {
+ typedef typename object_traits<T>::id_type id_type;
+
+ // Make sure that ID and T's object id types are the same
+ // (or implicit-convertible). If you get a compile error
+ // pointing here, then you most likely used a wrong object
+ // id argument in the constructor call.
+ //
+ const id_type& r (id);
+
+ reset_ (&db, &r, &free<id_type>, &copy<id_type>);
+ }
+
+ template <typename T>
+ inline lazy_ptr_impl<T>::
+ lazy_ptr_impl (const lazy_ptr_impl& r)
+ : lazy_ptr_base (r)
+ {
+ }
+
+ template <typename T>
+ template <typename Y>
+ inline lazy_ptr_impl<T>::
+ lazy_ptr_impl (const lazy_ptr_impl<Y>& r)
+ : lazy_ptr_base (r)
+ {
+ }
+
+ template <typename T>
+ inline lazy_ptr_impl<T>::
+ lazy_ptr_impl (const lazy_ptr_impl_ref& r)
+ : lazy_ptr_base (r)
+ {
+ }
+
+ template <typename T>
+ inline lazy_ptr_impl<T>& lazy_ptr_impl<T>::
+ operator= (const lazy_ptr_impl& r)
+ {
+ lazy_ptr_base& b (*this);
+ b = r;
+ return *this;
+ }
+
+ template <typename T>
+ template <typename Y>
+ inline lazy_ptr_impl<T>& lazy_ptr_impl<T>::
+ operator= (const lazy_ptr_impl<Y>& r)
+ {
+ lazy_ptr_base& b (*this);
+ b = r;
+ return *this;
+ }
+
+ template <typename T>
+ inline lazy_ptr_impl<T>& lazy_ptr_impl<T>::
+ operator= (const lazy_ptr_impl_ref& r)
+ {
+ lazy_ptr_base& b (*this);
+ b = r;
+ return *this;
+ }
+
+ template <typename T>
+ template <typename ID>
+ inline void lazy_ptr_impl<T>::
+ reset (database_type& db, const ID& id)
+ {
+ typedef typename object_traits<T>::id_type id_type;
+
+ // Make sure that ID and T's object id types are the same
+ // (or implicit-convertible). If you get a compile error
+ // pointing here, then you most likely used a wrong object
+ // id argument in the constructor call.
+ //
+ const id_type& r (id);
+
+ reset_ (&db, &r, &free<id_type>, &copy<id_type>);
+ }
+
+ template <typename T>
+ template <typename ID>
+ inline void lazy_ptr_impl<T>::
+ reset_id (const ID& id)
+ {
+ typedef typename object_traits<T>::id_type id_type;
+
+ // Make sure that ID and T's object id types are the same
+ // (or implicit-convertible). If you get a compile error
+ // pointing here, then you most likely used a wrong object
+ // id argument in the constructor call.
+ //
+ const id_type& r (id);
+
+ reset_ (db_, &r, &free<id_type>, &copy<id_type>);
+ }
+
+ template <typename T>
+ template <typename O>
+ inline typename object_traits<O>::id_type lazy_ptr_impl<T>::
+ object_id () const
+ {
+ typedef typename object_traits<T>::id_type id_type;
+ const id_type& id (*static_cast<const id_type*> (id_));
+
+ // Make sure that O' and T's object id types are the same
+ // (or implicit-convertible). If you get a compile error
+ // pointing here, then you most likely used a wrong type
+ // as a template argument in the object_id() call.
+ //
+ const typename object_traits<O>::id_type& r (id);
+ return r;
+ }
+}
diff --git a/odb/lazy-ptr-impl.txx b/odb/lazy-ptr-impl.txx
new file mode 100644
index 0000000..c3055c9
--- /dev/null
+++ b/odb/lazy-ptr-impl.txx
@@ -0,0 +1,51 @@
+// file : odb/lazy-ptr-impl.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/database.hxx>
+
+namespace odb
+{
+ //
+ // lazy_ptr_base
+ //
+
+ template <typename T>
+ void lazy_ptr_base::
+ free (void* p)
+ {
+ delete static_cast<T*> (p);
+ }
+
+ template <typename T>
+ void* lazy_ptr_base::
+ copy (const void* p)
+ {
+ return new T (*static_cast<const T*> (p));
+ }
+
+ //
+ // lazy_ptr_impl
+ //
+
+ template <typename T>
+ template <typename O>
+ inline typename object_traits<O>::pointer_type lazy_ptr_impl<T>::
+ load (bool reset)
+ {
+ typedef typename object_traits<T>::id_type id_type;
+ typedef typename object_traits<T>::pointer_type pointer_type;
+
+ const id_type& id (*static_cast<const id_type*> (id_));
+ pointer_type p (db_->load<T> (id));
+
+ if (reset)
+ reset_id ();
+
+ // If you get a compile error pointing here, then you most likely
+ // used a wrong type as a template argument in the load() call.
+ //
+ return p;
+ }
+}
diff --git a/odb/lazy-ptr.hxx b/odb/lazy-ptr.hxx
new file mode 100644
index 0000000..37786c7
--- /dev/null
+++ b/odb/lazy-ptr.hxx
@@ -0,0 +1,198 @@
+// file : odb/lazy-ptr.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_LAZY_PTR_HXX
+#define ODB_LAZY_PTR_HXX
+
+#include <odb/pre.hxx>
+
+#include <memory> // std::auto_ptr
+
+#include <odb/forward.hxx> // odb::database
+#include <odb/traits.hxx>
+#include <odb/lazy-ptr-impl.hxx>
+
+namespace odb
+{
+ template <class T>
+ class lazy_ptr
+ {
+ // Pointer interface.
+ //
+ public:
+ typedef T element_type;
+
+ lazy_ptr ();
+ template <class Y> lazy_ptr (Y*);
+
+ lazy_ptr (const lazy_ptr&);
+ template <class Y> lazy_ptr (const lazy_ptr<Y>&);
+
+ lazy_ptr& operator= (const lazy_ptr&);
+ template <class Y> lazy_ptr& operator= (Y*);
+ template <class Y> lazy_ptr& operator= (const lazy_ptr<Y>&);
+
+ void swap (lazy_ptr&);
+ void reset ();
+ template <class Y> void reset (Y*);
+
+ T& operator* () const;
+ T* operator-> () const;
+ T* get () const;
+
+ typedef T* lazy_ptr::*unspecified_bool_type;
+ operator unspecified_bool_type () const
+ {
+ return (p_ || i_) ? &lazy_ptr::p_ : 0;
+ }
+
+ // Lazy loading interface.
+ //
+ public:
+ typedef odb::database database_type;
+
+ bool loaded () const;
+ T* load () const;
+
+ // Unload the pointer. For transient objects this function is
+ // equivalent to reset().
+ //
+ void unload () const;
+
+ template <class ID> lazy_ptr (database_type&, const ID&);
+ template <class Y> lazy_ptr (database_type&, Y*);
+
+ template <class ID> void reset (database_type&, const ID&);
+ template <class Y> void reset (database_type&, Y*);
+
+ template <class O /* = T */>
+ typename object_traits<O>::id_type object_id () const;
+
+ database_type& database () const;
+
+ // Helpers.
+ //
+ public:
+ template <class Y> bool equal (const lazy_ptr<Y>&) const;
+
+ private:
+ template <class Y> friend class lazy_ptr;
+
+ mutable T* p_;
+ mutable lazy_ptr_impl<T> i_;
+ };
+
+ // operator< and operator<< are not provided.
+ //
+ template<class T, class Y>
+ bool operator== (const lazy_ptr<T>&, const lazy_ptr<Y>&);
+
+ template<class T, class Y>
+ bool operator!= (const lazy_ptr<T>&, const lazy_ptr<Y>&);
+
+ template<class T> void swap (lazy_ptr<T>&, lazy_ptr<T>&);
+
+ //
+ //
+ template <class T>
+ struct lazy_auto_ptr_ref
+ {
+ explicit lazy_auto_ptr_ref (T*, const lazy_ptr_impl_ref&);
+
+ T* p_;
+ lazy_ptr_impl_ref i_;
+ };
+
+ template <class T>
+ class lazy_auto_ptr
+ {
+ // Standard auto_ptr interface.
+ //
+ public:
+ typedef T element_type;
+
+ explicit lazy_auto_ptr (T* = 0);
+ lazy_auto_ptr (lazy_auto_ptr&);
+ template<class Y> lazy_auto_ptr (lazy_auto_ptr<Y>&);
+
+ lazy_auto_ptr& operator= (lazy_auto_ptr&);
+ template<class Y> lazy_auto_ptr& operator= (lazy_auto_ptr<Y>&);
+
+ T& operator* () const;
+ T* operator-> () const;
+ T* get () const;
+ T* release ();
+ void reset (T* = 0);
+
+ lazy_auto_ptr (const lazy_auto_ptr_ref<T>&);
+ lazy_auto_ptr& operator= (const lazy_auto_ptr_ref<T>&);
+ template<class Y> operator lazy_auto_ptr_ref<Y> ();
+ template<class Y> operator lazy_auto_ptr<Y> ();
+
+ // Extension: conversion to bool.
+ //
+ public:
+ typedef std::auto_ptr<T> lazy_auto_ptr::*unspecified_bool_type;
+ operator unspecified_bool_type () const
+ {
+ return (p_.get () != 0 || i_) ? &lazy_auto_ptr::p_ : 0;
+ }
+
+ // Initialization/assignment from auto_ptr.
+ //
+ public:
+ template <class Y> lazy_auto_ptr (std::auto_ptr<Y>&);
+ lazy_auto_ptr (std::auto_ptr_ref<T>);
+
+ template <class Y> lazy_auto_ptr& operator= (std::auto_ptr<Y>&);
+ lazy_auto_ptr& operator= (std::auto_ptr_ref<T>);
+
+ // Lazy loading interface.
+ //
+ public:
+ typedef odb::database database_type;
+
+ bool loaded () const;
+ std::auto_ptr<T>& load () const;
+
+ // Unload the pointer. For transient objects this function is
+ // equivalent to reset().
+ //
+ void unload () const;
+
+ template <class ID> lazy_auto_ptr (database_type&, const ID&);
+ lazy_auto_ptr (database_type&, T*);
+ template <class Y> lazy_auto_ptr (database_type&, std::auto_ptr<Y>&);
+
+ template <class ID> void reset (database_type&, const ID&);
+ void reset (database_type&, T*);
+ template <class Y> void reset (database_type&, std::auto_ptr<Y>&);
+
+ template <class O /* = T */>
+ typename object_traits<O>::id_type object_id () const;
+
+ database_type& database () const;
+
+ private:
+ template <class Y> friend class lazy_auto_ptr;
+
+ // Note that it is possible to have a situation where p_ is NULL,
+ // i_.id is NULL and i_.db is not NULL. This will happen if the
+ // auto_ptr reference returned by load() is transferred to another
+ // pointer or reset.
+ //
+ mutable std::auto_ptr<T> p_;
+ mutable lazy_ptr_impl<T> i_;
+ };
+}
+
+#include <odb/lazy-ptr.ixx>
+#include <odb/lazy-ptr.txx>
+
+#include <odb/lazy-pointer-traits.hxx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_LAZY_PTR_HXX
diff --git a/odb/lazy-ptr.ixx b/odb/lazy-ptr.ixx
new file mode 100644
index 0000000..3c27d20
--- /dev/null
+++ b/odb/lazy-ptr.ixx
@@ -0,0 +1,471 @@
+// file : odb/lazy-ptr.ixx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ //
+ // lazy_ptr
+ //
+
+ template <class T>
+ inline lazy_ptr<T>::
+ lazy_ptr (): p_ (0) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_ptr<T>::
+ lazy_ptr (Y* p): p_ (p) {}
+
+ template <class T>
+ inline lazy_ptr<T>::
+ lazy_ptr (const lazy_ptr& r): p_ (r.p_), i_ (r.i_) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_ptr<T>::
+ lazy_ptr (const lazy_ptr<Y>& r): p_ (r.p_), i_ (r.i_) {}
+
+ template <class T>
+ inline lazy_ptr<T>& lazy_ptr<T>::
+ operator= (const lazy_ptr& r)
+ {
+ p_ = r.p_;
+ i_ = r.i_;
+ return *this;
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_ptr<T>& lazy_ptr<T>::
+ operator= (Y* r)
+ {
+ p_ = r;
+ i_.reset ();
+ return *this;
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_ptr<T>& lazy_ptr<T>::
+ operator= (const lazy_ptr<Y>& r)
+ {
+ p_ = r.p_;
+ i_ = r.i_;
+ return *this;
+ }
+
+ template <class T>
+ inline void lazy_ptr<T>::
+ swap (lazy_ptr& b)
+ {
+ T* p (p_);
+ p_ = b.p_;
+ b.p_ = p;
+ i_.swap (b.i_);
+ }
+
+ template <class T>
+ inline void lazy_ptr<T>::
+ reset ()
+ {
+ p_ = 0;
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y>
+ inline void lazy_ptr<T>::
+ reset (Y* p)
+ {
+ p_ = p;
+ i_.reset ();
+ }
+
+ template <class T>
+ inline T& lazy_ptr<T>::
+ operator* () const
+ {
+ return *p_;
+ }
+
+ template <class T>
+ inline T* lazy_ptr<T>::
+ operator-> () const
+ {
+ return p_;
+ }
+
+ template <class T>
+ inline T* lazy_ptr<T>::
+ get () const
+ {
+ return p_;
+ }
+
+ template <class T>
+ inline bool lazy_ptr<T>::
+ loaded () const
+ {
+ return p_ || !i_;
+ }
+
+ template <class T>
+ inline T* lazy_ptr<T>::
+ load () const
+ {
+ if (!loaded ())
+ p_ = i_.template load<T> (true); // Reset id.
+
+ return p_;
+ }
+
+ template <class T>
+ inline void lazy_ptr<T>::
+ unload () const
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ if (p_)
+ {
+ if (i_.database () != 0)
+ i_.reset_id (object_traits<object_type>::id (*p_));
+
+ p_ = 0;
+ }
+ }
+
+ template <class T>
+ template <class ID>
+ inline lazy_ptr<T>::
+ lazy_ptr (database_type& db, const ID& id): p_ (0), i_ (db, id) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_ptr<T>::
+ lazy_ptr (database_type& db, Y* r)
+ : p_ (r)
+ {
+ if (p_)
+ i_.reset (db);
+ }
+
+ template <class T>
+ template <class ID>
+ inline void lazy_ptr<T>::
+ reset (database_type& db, const ID& id)
+ {
+ p_ = 0;
+ i_.reset (db, id);
+ }
+
+ template <class T>
+ template <class Y>
+ inline void lazy_ptr<T>::
+ reset (database_type& db, Y* r)
+ {
+ p_ = r;
+
+ if (p_)
+ i_.reset (db);
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class O>
+ inline typename object_traits<O>::id_type lazy_ptr<T>::
+ object_id () const
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ return p_ ? object_traits<object_type>::id (*p_) : i_.object_id<O> ();
+ }
+
+ template <class T>
+ inline typename lazy_ptr<T>::database_type& lazy_ptr<T>::
+ database () const
+ {
+ return *i_.database ();
+ }
+
+ template<class T, class Y>
+ inline bool
+ operator== (const lazy_ptr<T>& a, const lazy_ptr<Y>& b)
+ {
+ return a.equal (b);
+ }
+
+ template<class T, class Y>
+ inline bool
+ operator!= (const lazy_ptr<T>& a, const lazy_ptr<Y>& b)
+ {
+ return !a.equal (b);
+ }
+
+ template<class T>
+ inline void
+ swap (lazy_ptr<T>& a, lazy_ptr<T>& b)
+ {
+ a.swap (b);
+ }
+
+ //
+ // lazy_auto_ptr_ref
+ //
+
+ template<class T>
+ inline lazy_auto_ptr_ref<T>::
+ lazy_auto_ptr_ref (T* p, const lazy_ptr_impl_ref& i): p_ (p), i_ (i) {}
+
+ //
+ // lazy_auto_ptr
+ //
+
+ template<class T>
+ inline lazy_auto_ptr<T>::
+ lazy_auto_ptr (T* p): p_ (p) {}
+
+ template<class T>
+ inline lazy_auto_ptr<T>::
+ lazy_auto_ptr (lazy_auto_ptr& r)
+ : p_ (r.p_), i_ (static_cast<lazy_ptr_impl_ref> (r.i_))
+ {
+ }
+
+ template<class T>
+ template<class Y>
+ inline lazy_auto_ptr<T>::
+ lazy_auto_ptr (lazy_auto_ptr<Y>& r)
+ : p_ (r.p_), i_ (static_cast<lazy_ptr_impl_ref> (r.i_))
+ {
+ }
+
+ template<class T>
+ inline lazy_auto_ptr<T>& lazy_auto_ptr<T>::
+ operator= (lazy_auto_ptr& r)
+ {
+ p_ = r.p_;
+ i_ = static_cast<lazy_ptr_impl_ref> (r.i_);
+ return *this;
+ }
+
+ template<class T>
+ template<class Y>
+ inline lazy_auto_ptr<T>& lazy_auto_ptr<T>::
+ operator= (lazy_auto_ptr<Y>& r)
+ {
+ p_ = r.p_;
+ i_ = static_cast<lazy_ptr_impl_ref> (r.i_);
+ return *this;
+ }
+
+ template<class T>
+ inline T& lazy_auto_ptr<T>::
+ operator* () const
+ {
+ return *p_;
+ }
+
+ template<class T>
+ inline T* lazy_auto_ptr<T>::
+ operator-> () const
+ {
+ return p_.operator-> ();
+ }
+
+ template<class T>
+ inline T* lazy_auto_ptr<T>::
+ get () const
+ {
+ return p_.get ();
+ }
+
+ template<class T>
+ inline T* lazy_auto_ptr<T>::
+ release ()
+ {
+ i_.reset ();
+ return p_.release ();
+ }
+
+ template<class T>
+ inline void lazy_auto_ptr<T>::
+ reset (T* p)
+ {
+ i_.reset ();
+ p_.reset (p);
+ }
+
+ template<class T>
+ inline lazy_auto_ptr<T>::
+ lazy_auto_ptr (const lazy_auto_ptr_ref<T>& r): p_ (r.p_), i_ (r.i_) {}
+
+ template<class T>
+ inline lazy_auto_ptr<T>& lazy_auto_ptr<T>::
+ operator= (const lazy_auto_ptr_ref<T>& r)
+ {
+ if (p_.get () != r.p_)
+ p_.reset (r.p_);
+
+ i_ = r.i_;
+ return *this;
+ }
+
+ template<class T>
+ template<class Y>
+ inline lazy_auto_ptr<T>::
+ operator lazy_auto_ptr_ref<Y> ()
+ {
+ return lazy_auto_ptr_ref<Y> (p_.release (), i_);
+ }
+
+ template<class T>
+ template<class Y>
+ inline lazy_auto_ptr<T>::
+ operator lazy_auto_ptr<Y> ()
+ {
+ return lazy_auto_ptr<Y> (*this);
+ }
+
+ template<class T>
+ template <class Y>
+ inline lazy_auto_ptr<T>::
+ lazy_auto_ptr (std::auto_ptr<Y>& r): p_ (r) {}
+
+ template<class T>
+ inline lazy_auto_ptr<T>::
+ lazy_auto_ptr (std::auto_ptr_ref<T> r): p_ (r) {}
+
+ template<class T>
+ template <class Y>
+ inline lazy_auto_ptr<T>& lazy_auto_ptr<T>::
+ operator= (std::auto_ptr<Y>& r)
+ {
+ p_ = r;
+ i_.reset ();
+ return *this;
+ }
+
+ template<class T>
+ inline lazy_auto_ptr<T>& lazy_auto_ptr<T>::
+ operator= (std::auto_ptr_ref<T> r)
+ {
+ p_ = r;
+ i_.reset ();
+ return *this;
+ }
+
+ template <class T>
+ inline bool lazy_auto_ptr<T>::
+ loaded () const
+ {
+ return p_.get () != 0 || !i_;
+ }
+
+ template <class T>
+ inline std::auto_ptr<T>& lazy_auto_ptr<T>::
+ load () const
+ {
+ if (!loaded ())
+ {
+ std::auto_ptr<T> tmp (i_.template load<T> (true)); // Reset id.
+ p_ = tmp;
+ }
+
+ return p_;
+ }
+
+ template <class T>
+ inline void lazy_auto_ptr<T>::
+ unload () const
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ if (p_.get () != 0)
+ {
+ if (i_.database () != 0)
+ i_.reset_id (object_traits<object_type>::id (*p_));
+
+ p_.reset ();
+ }
+ }
+
+ template <class T>
+ template <class ID>
+ inline lazy_auto_ptr<T>::
+ lazy_auto_ptr (database_type& db, const ID& id): i_ (db, id) {}
+
+ template <class T>
+ inline lazy_auto_ptr<T>::
+ lazy_auto_ptr (database_type& db, T* p)
+ : p_ (p)
+ {
+ if (p)
+ i_.reset (db);
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_auto_ptr<T>::
+ lazy_auto_ptr (database_type& db, std::auto_ptr<Y>& p)
+ : p_ (p)
+ {
+ if (p)
+ i_.reset (db);
+ }
+
+ template <class T>
+ template <class ID>
+ inline void lazy_auto_ptr<T>::
+ reset (database_type& db, const ID& id)
+ {
+ p_.reset ();
+ i_.reset (db, id);
+ }
+
+ template <class T>
+ inline void lazy_auto_ptr<T>::
+ reset (database_type& db, T* p)
+ {
+ p_.reset (p);
+
+ if (p)
+ i_.reset (db);
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y>
+ inline void lazy_auto_ptr<T>::
+ reset (database_type& db, std::auto_ptr<Y>& p)
+ {
+ p_ = p;
+
+ if (p_.get () != 0)
+ i_.reset (db);
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class O>
+ inline typename object_traits<O>::id_type lazy_auto_ptr<T>::
+ object_id () const
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ return p_.get () != 0
+ ? object_traits<object_type>::id (*p_)
+ : i_.object_id<O> ();
+ }
+
+ template <class T>
+ inline typename lazy_auto_ptr<T>::database_type& lazy_auto_ptr<T>::
+ database () const
+ {
+ return *i_.database ();
+ }
+}
diff --git a/odb/lazy-ptr.txx b/odb/lazy-ptr.txx
new file mode 100644
index 0000000..c016588
--- /dev/null
+++ b/odb/lazy-ptr.txx
@@ -0,0 +1,30 @@
+// file : odb/lazy-ptr.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ //
+ // lazy_ptr
+ //
+
+ template <class T>
+ template <class Y>
+ bool lazy_ptr<T>::
+ equal (const lazy_ptr<Y>& r) const
+ {
+ if (loaded () && r.loaded ())
+ return p_ == r.p_;
+
+ // If one of the object is not loaded, then we compare databases and
+ // object ids. Note that NULL pointers cannot have non-NULL databases
+ // and if both of them are NULL, we wouldn't have gotten here.
+ //
+ typedef typename object_traits<T>::object_type object_type1;
+ typedef typename object_traits<Y>::object_type object_type2;
+
+ return i_.database () == r.i_.database () &&
+ object_id<object_type1> () == r.object_id<object_type2> ();
+ }
+}
diff --git a/odb/pointer-traits.hxx b/odb/pointer-traits.hxx
index 90d9b4b..07cc253 100644
--- a/odb/pointer-traits.hxx
+++ b/odb/pointer-traits.hxx
@@ -76,6 +76,7 @@ namespace odb
{
public:
static pointer_kind const kind = pk_naked;
+ static bool const lazy = false;
typedef T element_type;
typedef T* pointer_type;
@@ -136,6 +137,7 @@ namespace odb
{
public:
static pointer_kind const kind = pk_unique;
+ static bool const lazy = false;
typedef T element_type;
typedef std::auto_ptr<element_type> pointer_type;
diff --git a/odb/tr1-pointer-traits.hxx b/odb/tr1-pointer-traits.hxx
index c21d46a..bbeceab 100644
--- a/odb/tr1-pointer-traits.hxx
+++ b/odb/tr1-pointer-traits.hxx
@@ -24,6 +24,7 @@ namespace odb
{
public:
static pointer_kind const kind = pk_shared;
+ static bool const lazy = false;
typedef T element_type;
typedef std::tr1::shared_ptr<element_type> pointer_type;
@@ -45,7 +46,7 @@ namespace odb
static bool
null_ptr (const pointer_type& p)
{
- return p.get () == 0;
+ return !p;
}
public:
@@ -69,12 +70,17 @@ namespace odb
{
public:
static pointer_kind const kind = pk_weak;
+ static bool const lazy = false;
typedef T element_type;
typedef std::tr1::weak_ptr<element_type> pointer_type;
- typedef std::tr1::weak_ptr<const element_type> const_pointer_type;
typedef std::tr1::shared_ptr<element_type> strong_pointer_type;
- typedef std::tr1::shared_ptr<const element_type> strong_const_pointer_type;
+
+ static strong_pointer_type
+ lock (const pointer_type& p)
+ {
+ return p.lock ();
+ }
};
}
diff --git a/odb/tr1/lazy-pointer-traits.hxx b/odb/tr1/lazy-pointer-traits.hxx
new file mode 100644
index 0000000..74276c5
--- /dev/null
+++ b/odb/tr1/lazy-pointer-traits.hxx
@@ -0,0 +1,63 @@
+// file : odb/tr1/lazy-pointer-traits.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_TR1_LAZY_POINTER_TRAITS_HXX
+#define ODB_TR1_LAZY_POINTER_TRAITS_HXX
+
+#include <odb/pre.hxx>
+
+#include <odb/pointer-traits.hxx>
+#include <odb/tr1/lazy-ptr.hxx>
+
+namespace odb
+{
+ template <typename T>
+ class pointer_traits< tr1::lazy_shared_ptr<T> >
+ {
+ public:
+ static pointer_kind const kind = pk_shared;
+ static bool const lazy = true;
+
+ typedef T element_type;
+ typedef tr1::lazy_shared_ptr<element_type> pointer_type;
+ typedef std::tr1::shared_ptr<element_type> eager_pointer_type;
+
+ static bool
+ null_ptr (const pointer_type& p)
+ {
+ return !p;
+ }
+
+ template <class O /* = T */>
+ static typename object_traits<O>::id_type
+ object_id (const pointer_type& p)
+ {
+ return p.object_id<O> ();
+ }
+ };
+
+ template <typename T>
+ class pointer_traits< tr1::lazy_weak_ptr<T> >
+ {
+ public:
+ static pointer_kind const kind = pk_weak;
+ static bool const lazy = true;
+
+ typedef T element_type;
+ typedef tr1::lazy_weak_ptr<element_type> pointer_type;
+ typedef tr1::lazy_shared_ptr<element_type> strong_pointer_type;
+ typedef std::tr1::weak_ptr<element_type> eager_pointer_type;
+
+ static strong_pointer_type
+ lock (const pointer_type& p)
+ {
+ return p.lock ();
+ }
+ };
+}
+
+#include <odb/post.hxx>
+
+#endif // ODB_TR1_LAZY_POINTER_TRAITS_HXX
diff --git a/odb/tr1/lazy-ptr.hxx b/odb/tr1/lazy-ptr.hxx
new file mode 100644
index 0000000..ea9bf78
--- /dev/null
+++ b/odb/tr1/lazy-ptr.hxx
@@ -0,0 +1,239 @@
+// file : odb/tr1/lazy-ptr.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_TR1_LAZY_PTR_HXX
+#define ODB_TR1_LAZY_PTR_HXX
+
+#include <odb/pre.hxx>
+
+//
+// This header assumes that the necessary TR1 header has already
+// been included.
+//
+
+#include <memory> // std::auto_ptr
+
+#include <odb/forward.hxx> // odb::database
+#include <odb/traits.hxx>
+#include <odb/lazy-ptr-impl.hxx>
+
+namespace odb
+{
+ namespace tr1
+ {
+ template <class T>
+ class lazy_weak_ptr;
+
+ //
+ //
+ template <class T>
+ class lazy_shared_ptr
+ {
+ // The standard shared_ptr interface.
+ //
+ public:
+ typedef T element_type;
+
+ lazy_shared_ptr ();
+ template <class Y> explicit lazy_shared_ptr (Y*);
+ template <class Y, class D> lazy_shared_ptr (Y*, D);
+ template <class Y, class D, class A> lazy_shared_ptr (Y*, D, A);
+
+ lazy_shared_ptr (const lazy_shared_ptr&);
+ template <class Y> lazy_shared_ptr (const lazy_shared_ptr<Y>&);
+ template <class Y> explicit lazy_shared_ptr (const lazy_weak_ptr<Y>&);
+ template <class Y> explicit lazy_shared_ptr (std::auto_ptr<Y>&);
+
+ ~lazy_shared_ptr ();
+
+ lazy_shared_ptr& operator= (const lazy_shared_ptr&);
+ template <class Y> lazy_shared_ptr& operator= (const lazy_shared_ptr<Y>&);
+ template <class Y> lazy_shared_ptr& operator= (std::auto_ptr<Y>&);
+
+ void swap (lazy_shared_ptr&);
+ void reset ();
+ template <class Y> void reset (Y*);
+ template <class Y, class D> void reset (Y*, D);
+ template <class Y, class D, class A> void reset (Y*, D, A);
+
+ T& operator* () const;
+ T* operator-> () const;
+ T* get () const;
+
+ bool unique () const;
+ long use_count () const;
+
+ typedef std::tr1::shared_ptr<T> lazy_shared_ptr::*unspecified_bool_type;
+ operator unspecified_bool_type () const
+ {
+ return (p_ || i_) ? &lazy_shared_ptr::p_ : 0;
+ }
+
+ // Initialization/assignment from shared_ptr and weak_ptr.
+ //
+ public:
+ template <class Y> lazy_shared_ptr (const std::tr1::shared_ptr<Y>&);
+ template <class Y> explicit lazy_shared_ptr (const std::tr1::weak_ptr<Y>&);
+
+ template <class Y> lazy_shared_ptr& operator= (const std::tr1::shared_ptr<Y>&);
+
+ // Lazy loading interface.
+ //
+ public:
+ typedef odb::database database_type;
+
+ bool loaded () const;
+ std::tr1::shared_ptr<T> load () const;
+
+ // Unload the pointer. For transient objects this function is
+ // equivalent to reset().
+ //
+ void unload () const;
+
+ template <class ID> lazy_shared_ptr (database_type&, const ID&);
+ template <class Y> lazy_shared_ptr (database_type&, Y*);
+ template <class Y, class D> lazy_shared_ptr (database_type&, Y*, D);
+ template <class Y, class D, class A> lazy_shared_ptr (database_type&, Y*, D, A);
+ template <class Y> lazy_shared_ptr (database_type&, std::auto_ptr<Y>&);
+ template <class Y> lazy_shared_ptr (database_type&, const std::tr1::shared_ptr<Y>&);
+ template <class Y> lazy_shared_ptr (database_type&, const std::tr1::weak_ptr<Y>&);
+
+ template <class ID> void reset (database_type&, const ID&);
+ template <class Y> void reset (database_type&, Y*);
+ template <class Y, class D> void reset (database_type&, Y*, D);
+ template <class Y, class D, class A> void reset (database_type&, Y*, D, A);
+ template <class Y> void reset (database_type&, const std::auto_ptr<Y>&);
+ template <class Y> void reset (database_type&, const std::tr1::shared_ptr<Y>&);
+
+ template <class O /* = T */>
+ typename object_traits<O>::id_type object_id () const;
+
+ database_type& database () const;
+
+ // Helpers.
+ //
+ public:
+ template <class Y> bool equal (const lazy_shared_ptr<Y>&) const;
+
+ private:
+ template <class Y> friend class lazy_shared_ptr;
+ template <class Y> friend class lazy_weak_ptr;
+
+ mutable std::tr1::shared_ptr<T> p_;
+ mutable lazy_ptr_impl<T> i_;
+ };
+
+ // operator< and operator<< are not provided.
+ //
+ template<class T, class Y>
+ bool operator== (const lazy_shared_ptr<T>&, const lazy_shared_ptr<Y>&);
+
+ template<class T, class Y>
+ bool operator!= (const lazy_shared_ptr<T>&, const lazy_shared_ptr<Y>&);
+
+ template<class T> void swap (lazy_shared_ptr<T>&, lazy_shared_ptr<T>&);
+
+ template<class D, class T>
+ D* get_deleter (const lazy_shared_ptr<T>&);
+
+ //
+ //
+ template <class T>
+ class lazy_weak_ptr
+ {
+ // The standard weak_ptr interface.
+ //
+ public:
+ typedef T element_type;
+
+ lazy_weak_ptr ();
+ template <class Y> lazy_weak_ptr (const lazy_shared_ptr<Y>&);
+ lazy_weak_ptr (const lazy_weak_ptr&);
+ template <class Y> lazy_weak_ptr (const lazy_weak_ptr<Y>&);
+
+ ~lazy_weak_ptr ();
+
+ lazy_weak_ptr& operator= (const lazy_weak_ptr&);
+ template <class Y> lazy_weak_ptr& operator= (const lazy_weak_ptr<Y>&);
+ template <class Y> lazy_weak_ptr& operator= (const lazy_shared_ptr<Y>&);
+
+ void swap (lazy_weak_ptr<T>&);
+ void reset ();
+
+ long use_count () const;
+ bool expired () const;
+
+ lazy_shared_ptr<T> lock () const;
+
+ // Initialization/assignment from shared_ptr and weak_ptr.
+ //
+ public:
+ template <class Y> lazy_weak_ptr (const std::tr1::weak_ptr<Y>&);
+ template <class Y> lazy_weak_ptr (const std::tr1::shared_ptr<Y>&);
+
+ template <class Y> lazy_weak_ptr& operator= (const std::tr1::weak_ptr<Y>&);
+ template <class Y> lazy_weak_ptr& operator= (const std::tr1::shared_ptr<Y>&);
+
+ // Lazy loading interface.
+ //
+ public:
+ typedef odb::database database_type;
+
+ // expired() loaded()
+ //
+ // true true expired pointer to transient object
+ // false true valid pointer to persistent object
+ // true false expired pointer to persistent object
+ // false false valid pointer to transiend object
+ //
+ bool loaded () const;
+
+ // Performs both lock and load.
+ //
+ std::tr1::shared_ptr<T> load () const;
+
+ // Unload the pointer. For transient objects this function is
+ // equivalent to reset().
+ //
+ void unload () const;
+
+ template <class ID> lazy_weak_ptr (database_type&, const ID&);
+ template <class Y> lazy_weak_ptr (database_type&, const std::tr1::shared_ptr<Y>&);
+ template <class Y> lazy_weak_ptr (database_type&, const std::tr1::weak_ptr<Y>&);
+
+ template <class ID> void reset (database_type&, const ID&);
+ template <class Y> void reset (database_type&, const std::tr1::shared_ptr<Y>&);
+ template <class Y> void reset (database_type&, const std::tr1::weak_ptr<Y>&);
+
+ // The object_id() function can only be called when the object is
+ // persistent, or: expired() XOR loaded() (can use != for XOR).
+ //
+ template <class O /* = T */>
+ typename object_traits<O>::id_type object_id () const;
+
+ database_type& database () const;
+
+ private:
+ template <class Y> friend class lazy_shared_ptr;
+ template <class Y> friend class lazy_weak_ptr;
+
+ mutable std::tr1::weak_ptr<T> p_;
+ mutable lazy_ptr_impl<T> i_;
+ };
+
+ // operator< is not provided.
+ //
+ template<class T> void swap (lazy_weak_ptr<T>&, lazy_weak_ptr<T>&);
+ }
+}
+
+#include <odb/tr1/lazy-ptr.ixx>
+#include <odb/tr1/lazy-ptr.txx>
+
+#include <odb/tr1/lazy-pointer-traits.hxx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_TR1_LAZY_PTR_HXX
diff --git a/odb/tr1/lazy-ptr.ixx b/odb/tr1/lazy-ptr.ixx
new file mode 100644
index 0000000..3e217b1
--- /dev/null
+++ b/odb/tr1/lazy-ptr.ixx
@@ -0,0 +1,649 @@
+// file : odb/tr1/lazy-ptr.ixx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ namespace tr1
+ {
+ //
+ // lazy_shared_ptr
+ //
+
+ template <class T>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr () {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (Y* p): p_ (p) {}
+
+ template <class T>
+ template <class Y, class D>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (Y* p, D d): p_ (p, d) {}
+
+ template <class T>
+ template <class Y, class D, class A>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (Y* p, D d, A a): p_ (p, d, a) {}
+
+ template <class T>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (const lazy_shared_ptr<Y>& r): p_ (r.p_), i_ (r.i_) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (const lazy_weak_ptr<Y>& r): i_ (r.i_)
+ {
+ // If the pointer has expired but can be re-loaded, then don't throw.
+ //
+ p_ = r.lock ();
+
+ if (!p_ && !i_)
+ throw std::tr1::bad_weak_ptr ();
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (std::auto_ptr<Y>& r): p_ (r) {}
+
+ template <class T>
+ inline lazy_shared_ptr<T>::
+ ~lazy_shared_ptr () {}
+
+ template <class T>
+ inline lazy_shared_ptr<T>& lazy_shared_ptr<T>::
+ operator= (const lazy_shared_ptr& r)
+ {
+ p_ = r.p_;
+ i_ = r.i_;
+ return *this;
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>& lazy_shared_ptr<T>::
+ operator= (const lazy_shared_ptr<Y>& r)
+ {
+ p_ = r.p_;
+ i_ = r.i_;
+ return *this;
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>& lazy_shared_ptr<T>::
+ operator= (std::auto_ptr<Y>& r)
+ {
+ p_ = r;
+ i_.reset ();
+ return *this;
+ }
+
+ template <class T>
+ inline void lazy_shared_ptr<T>::
+ swap (lazy_shared_ptr& b)
+ {
+ p_.swap (b.p_);
+ i_.swap (b.i_);
+ }
+
+ template <class T>
+ inline void lazy_shared_ptr<T>::
+ reset ()
+ {
+ p_.reset ();
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y>
+ inline void lazy_shared_ptr<T>::
+ reset (Y* p)
+ {
+ p_.reset (p);
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y, class D>
+ inline void lazy_shared_ptr<T>::
+ reset (Y* p, D d)
+ {
+ p_.reset (p, d);
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y, class D, class A>
+ inline void lazy_shared_ptr<T>::
+ reset (Y* p, D d, A a)
+ {
+ p_.reset (p, d, a);
+ i_.reset ();
+ }
+
+ template <class T>
+ inline T& lazy_shared_ptr<T>::
+ operator* () const
+ {
+ return *p_;
+ }
+
+ template <class T>
+ inline T* lazy_shared_ptr<T>::
+ operator-> () const
+ {
+ return p_.operator-> ();
+ }
+
+ template <class T>
+ inline T* lazy_shared_ptr<T>::
+ get () const
+ {
+ return p_.get ();
+ }
+
+ template <class T>
+ inline bool lazy_shared_ptr<T>::
+ unique () const
+ {
+ return p_.unique ();
+ }
+
+ template <class T>
+ inline long lazy_shared_ptr<T>::
+ use_count () const
+ {
+ return p_.use_count ();
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (const std::tr1::shared_ptr<Y>& r): p_ (r) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (const std::tr1::weak_ptr<Y>& r): p_ (r) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>& lazy_shared_ptr<T>::
+ operator= (const std::tr1::shared_ptr<Y>& r)
+ {
+ p_ = r;
+ i_.reset ();
+ return *this;
+ }
+
+ template <class T>
+ inline bool lazy_shared_ptr<T>::
+ loaded () const
+ {
+ return p_ || !i_;
+ }
+
+ template <class T>
+ inline std::tr1::shared_ptr<T> lazy_shared_ptr<T>::
+ load () const
+ {
+ if (!loaded ())
+ p_ = i_.template load<T> (true); // Reset id.
+
+ return p_;
+ }
+
+ template <class T>
+ inline void lazy_shared_ptr<T>::
+ unload () const
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ if (p_)
+ {
+ if (i_.database () != 0)
+ i_.reset_id (object_traits<object_type>::id (*p_));
+
+ p_.reset ();
+ }
+ }
+
+ template <class T>
+ template <class ID>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (database_type& db, const ID& id): i_ (db, id) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (database_type& db, Y* p)
+ : p_ (p)
+ {
+ if (p_)
+ i_.reset (db);
+ }
+
+ template <class T>
+ template <class Y, class D>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (database_type& db, Y* p, D d)
+ : p_ (p, d)
+ {
+ if (p_)
+ i_.reset (db);
+ }
+
+ template <class T>
+ template <class Y, class D, class A>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (database_type& db, Y* p, D d, A a)
+ : p_ (p, d, a)
+ {
+ if (p_)
+ i_.reset (db);
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (database_type& db, std::auto_ptr<Y>& r)
+ : p_ (r)
+ {
+ if (p_)
+ i_.reset (db);
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (database_type& db, const std::tr1::shared_ptr<Y>& r)
+ : p_ (r)
+ {
+ if (p_)
+ i_.reset (db);
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_shared_ptr<T>::
+ lazy_shared_ptr (database_type& db, const std::tr1::weak_ptr<Y>& r)
+ : p_ (r)
+ {
+ if (p_)
+ i_.reset (db);
+ }
+
+ template <class T>
+ template <class ID>
+ inline void lazy_shared_ptr<T>::
+ reset (database_type& db, const ID& id)
+ {
+ p_.reset ();
+ i_.reset (db, id);
+ }
+
+ template <class T>
+ template <class Y>
+ inline void lazy_shared_ptr<T>::
+ reset (database_type& db, Y* p)
+ {
+ p_.reset (p);
+
+ if (p_)
+ i_.reset (db);
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y, class D>
+ inline void lazy_shared_ptr<T>::
+ reset (database_type& db, Y* p, D d)
+ {
+ p_.reset (p, d);
+
+ if (p_)
+ i_.reset (db);
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y, class D, class A>
+ inline void lazy_shared_ptr<T>::
+ reset (database_type& db, Y* p, D d, A a)
+ {
+ p_.reset (p, d, a);
+
+ if (p_)
+ i_.reset (db);
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y>
+ inline void lazy_shared_ptr<T>::
+ reset (database_type& db, const std::auto_ptr<Y>& r)
+ {
+ p_ = r;
+
+ if (p_)
+ i_.reset (db);
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y>
+ inline void lazy_shared_ptr<T>::
+ reset (database_type& db, const std::tr1::shared_ptr<Y>& r)
+ {
+ p_ = r;
+
+ if (p_)
+ i_.reset (db);
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class O>
+ inline typename object_traits<O>::id_type lazy_shared_ptr<T>::
+ object_id () const
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ return p_ ? object_traits<object_type>::id (*p_) : i_.object_id<O> ();
+ }
+
+ template <class T>
+ inline typename lazy_shared_ptr<T>::database_type& lazy_shared_ptr<T>::
+ database () const
+ {
+ return *i_.database ();
+ }
+
+ template<class T, class Y>
+ inline bool
+ operator== (const lazy_shared_ptr<T>& a, const lazy_shared_ptr<Y>& b)
+ {
+ return a.equal (b);
+ }
+
+ template<class T, class Y>
+ inline bool
+ operator!= (const lazy_shared_ptr<T>& a, const lazy_shared_ptr<Y>& b)
+ {
+ return !a.equal (b);
+ }
+
+ template<class T>
+ inline void
+ swap (lazy_shared_ptr<T>& a, lazy_shared_ptr<T>& b)
+ {
+ a.swap (b);
+ }
+
+ template<class D, class T>
+ inline D*
+ get_deleter (const lazy_shared_ptr<T>& p)
+ {
+ return std::tr1::get_deleter<D> (p.p_);
+ }
+
+
+ //
+ // lazy_weak_ptr
+ //
+
+ template <class T>
+ inline lazy_weak_ptr<T>::
+ lazy_weak_ptr () {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>::
+ lazy_weak_ptr (const lazy_shared_ptr<Y>& r): p_ (r.p_), i_ (r.i_) {}
+
+ template <class T>
+ inline lazy_weak_ptr<T>::
+ lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>::
+ lazy_weak_ptr (const lazy_weak_ptr<Y>& r): p_ (r.p_), i_ (r.i_) {}
+
+ template <class T>
+ inline lazy_weak_ptr<T>::
+ ~lazy_weak_ptr () {}
+
+ template <class T>
+ inline lazy_weak_ptr<T>& lazy_weak_ptr<T>::
+ operator= (const lazy_weak_ptr& r)
+ {
+ p_ = r.p_;
+ i_ = r.i_;
+ return *this;
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>& lazy_weak_ptr<T>::
+ operator= (const lazy_weak_ptr<Y>& r)
+ {
+ p_ = r.p_;
+ i_ = r.i_;
+ return *this;
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>& lazy_weak_ptr<T>::
+ operator= (const lazy_shared_ptr<Y>& r)
+ {
+ p_ = r.p_;
+ i_ = r.i_;
+ return *this;
+ }
+
+ template <class T>
+ inline void lazy_weak_ptr<T>::
+ swap (lazy_weak_ptr<T>& r)
+ {
+ p_.swap (r.p_);
+ i_.swap (r.i_);
+ }
+
+ template <class T>
+ inline void lazy_weak_ptr<T>::
+ reset ()
+ {
+ p_.reset ();
+ i_.reset ();
+ }
+
+ template <class T>
+ inline long lazy_weak_ptr<T>::
+ use_count () const
+ {
+ return p_.use_count ();
+ }
+
+ template <class T>
+ inline bool lazy_weak_ptr<T>::
+ expired () const
+ {
+ return p_.expired ();
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>::
+ lazy_weak_ptr (const std::tr1::weak_ptr<Y>& r): p_ (r) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>::
+ lazy_weak_ptr (const std::tr1::shared_ptr<Y>& r): p_ (r) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>& lazy_weak_ptr<T>::
+ operator= (const std::tr1::weak_ptr<Y>& r)
+ {
+ p_ = r;
+ i_.reset ();
+ return this;
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>& lazy_weak_ptr<T>::
+ operator= (const std::tr1::shared_ptr<Y>& r)
+ {
+ p_ = r;
+ i_.reset ();
+ return this;
+ }
+
+ template <class T>
+ inline bool lazy_weak_ptr<T>::
+ loaded () const
+ {
+ return !expired () || !i_;
+ }
+
+ template <class T>
+ inline std::tr1::shared_ptr<T> lazy_weak_ptr<T>::
+ load () const
+ {
+ std::tr1::shared_ptr<T> r (p_.lock ());
+
+ if (r || !i_)
+ return r;
+
+ r = i_.template load<T> (false); // Keep id.
+ p_ = r;
+ return r;
+ }
+
+ template <class T>
+ inline void lazy_weak_ptr<T>::
+ unload () const
+ {
+ // With weak pointer we always keep i_ up to date.
+ //
+ p_.reset ();
+ }
+
+ template <class T>
+ template <class ID>
+ inline lazy_weak_ptr<T>::
+ lazy_weak_ptr (database_type& db, const ID& id): i_ (db, id) {}
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>::
+ lazy_weak_ptr (database_type& db, const std::tr1::shared_ptr<Y>& r)
+ : p_ (r)
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ if (r)
+ i_.reset (db, object_traits<object_type>::id (*r));
+ }
+
+ template <class T>
+ template <class Y>
+ inline lazy_weak_ptr<T>::
+ lazy_weak_ptr (database_type& db, const std::tr1::weak_ptr<Y>& r)
+ : p_ (r)
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ std::tr1::shared_ptr<T> sp (p_.lock ());
+
+ if (sp)
+ i_.reset (db, object_traits<object_type>::id (*sp));
+ }
+
+ template <class T>
+ template <class ID>
+ inline void lazy_weak_ptr<T>::
+ reset (database_type& db, const ID& id)
+ {
+ p_.reset ();
+ i_.reset (db, id);
+ }
+
+ template <class T>
+ template <class Y>
+ inline void lazy_weak_ptr<T>::
+ reset (database_type& db, const std::tr1::shared_ptr<Y>& r)
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ p_ = r;
+
+ if (r)
+ i_.reset (db, object_traits<object_type>::id (*r));
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class Y>
+ inline void lazy_weak_ptr<T>::
+ reset (database_type& db, const std::tr1::weak_ptr<Y>& r)
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ p_ = r;
+ std::tr1::shared_ptr<T> sp (p_.lock ());
+
+ if (sp)
+ i_.reset (db, object_traits<object_type>::id (*sp));
+ else
+ i_.reset ();
+ }
+
+ template <class T>
+ template <class O>
+ inline typename object_traits<O>::id_type lazy_weak_ptr<T>::
+ object_id () const
+ {
+ typedef typename object_traits<T>::object_type object_type;
+
+ std::tr1::shared_ptr<T> sp (p_.lock ());
+ return sp ? object_traits<object_type>::id (*sp) : i_.object_id<O> ();
+ }
+
+ template <class T>
+ inline typename lazy_weak_ptr<T>::database_type& lazy_weak_ptr<T>::
+ database () const
+ {
+ return *i_.database ();
+ }
+
+ template<class T>
+ inline void
+ swap (lazy_weak_ptr<T>& a, lazy_weak_ptr<T>& b)
+ {
+ a.swap (b);
+ }
+ }
+}
diff --git a/odb/tr1/lazy-ptr.txx b/odb/tr1/lazy-ptr.txx
new file mode 100644
index 0000000..b7b5bc5
--- /dev/null
+++ b/odb/tr1/lazy-ptr.txx
@@ -0,0 +1,59 @@
+// file : odb/tr1/lazy-ptr.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ namespace tr1
+ {
+ //
+ // lazy_shared_ptr
+ //
+
+ template <class T>
+ template <class Y>
+ bool lazy_shared_ptr<T>::
+ equal (const lazy_shared_ptr<Y>& r) const
+ {
+ if (loaded () && r.loaded ())
+ return p_ == r.p_;
+
+ // If one of the object is not loaded, then we compare databases and
+ // object ids. Note that NULL pointers cannot have non-NULL databases
+ // and if both of them are NULL, we wouldn't have gotten here.
+ //
+ typedef typename object_traits<T>::object_type object_type1;
+ typedef typename object_traits<Y>::object_type object_type2;
+
+ return i_.database () == r.i_.database () &&
+ object_id<object_type1> () == r.object_id<object_type2> ();
+ }
+
+ //
+ // lazy_weak_ptr
+ //
+
+ template <class T>
+ lazy_shared_ptr<T> lazy_weak_ptr<T>::
+ lock () const
+ {
+ std::tr1::shared_ptr<T> sp (p_.lock ());
+
+ if (sp)
+ {
+ if (database_type* db = i_.database ())
+ return lazy_shared_ptr<T> (*db, sp);
+ else
+ return lazy_shared_ptr<T> (sp);
+ }
+ else
+ {
+ if (i_)
+ return lazy_shared_ptr<T> (*i_.database (), i_.object_id<T> ());
+ else
+ return lazy_shared_ptr<T> ();
+ }
+ }
+ }
+}