// file : odb/lazy-ptr.hxx // copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file #ifndef ODB_LAZY_PTR_HXX #define ODB_LAZY_PTR_HXX #include #include // std::auto_ptr, std::shared_ptr/weak_ptr #include // std::move #include // odb::core, odb::database #include #include #include // ODB_CXX11 namespace odb { // Raw pointer lazy version. // template class lazy_ptr { // Pointer interface. // public: typedef T element_type; lazy_ptr (); template lazy_ptr (Y*); lazy_ptr (const lazy_ptr&); template lazy_ptr (const lazy_ptr&); lazy_ptr& operator= (const lazy_ptr&); template lazy_ptr& operator= (Y*); template lazy_ptr& operator= (const lazy_ptr&); void swap (lazy_ptr&); void reset (); template 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; // NULL loaded() // // true true NULL pointer to transient object // false true valid pointer to persistent object // true false unloaded pointer to persistent object // false false valid pointer to transient object // bool loaded () const; T* load () const; // Unload the pointer. For transient objects this function is // equivalent to reset(). // void unload () const; // Get the underlying eager pointer. If this is an unloaded pointer // to a persistent object, then the returned pointer will be NULL. // T* get_eager () const; template lazy_ptr (DB&, const ID&); template lazy_ptr (DB&, Y*); template void reset (DB&, const ID&); template void reset (DB&, Y*); #ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT template #else template #endif typename object_traits::id_type object_id () const; database_type& database () const; // Helpers. // public: template bool equal (const lazy_ptr&) const; private: template friend class lazy_ptr; mutable T* p_; mutable lazy_ptr_impl i_; }; // operator< and operator<< are not provided. // template bool operator== (const lazy_ptr&, const lazy_ptr&); template bool operator!= (const lazy_ptr&, const lazy_ptr&); template void swap (lazy_ptr&, lazy_ptr&); // std::auto_ptr lazy version. // #ifndef ODB_CXX11 template 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 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 lazy_auto_ptr (lazy_auto_ptr&); lazy_auto_ptr& operator= (lazy_auto_ptr&); template lazy_auto_ptr& operator= (lazy_auto_ptr&); T& operator* () const; T* operator-> () const; T* get () const; T* release (); void reset (T* = 0); lazy_auto_ptr (const lazy_auto_ptr_ref&); lazy_auto_ptr& operator= (const lazy_auto_ptr_ref&); template operator lazy_auto_ptr_ref (); template operator lazy_auto_ptr (); // Extension: conversion to bool. // public: typedef std::auto_ptr 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 lazy_auto_ptr (std::auto_ptr&); lazy_auto_ptr (std::auto_ptr_ref); template lazy_auto_ptr& operator= (std::auto_ptr&); lazy_auto_ptr& operator= (std::auto_ptr_ref); // Lazy loading interface. // public: typedef odb::database database_type; // NULL loaded() // // true true NULL pointer to transient object // false true valid pointer to persistent object // true false unloaded pointer to persistent object // false false valid pointer to transient object // bool loaded () const; std::auto_ptr& load () const; // Unload the pointer. For transient objects this function is // equivalent to reset(). // void unload () const; // Get the underlying eager pointer. If this is an unloaded pointer // to a persistent object, then the returned pointer will be NULL. // std::auto_ptr& get_eager () const; template lazy_auto_ptr (DB&, const ID&); template lazy_auto_ptr (DB&, T*); template lazy_auto_ptr (DB&, std::auto_ptr&); template void reset (DB&, const ID&); template void reset (DB&, T*); template void reset (DB&, std::auto_ptr&); template typename object_traits::id_type object_id () const; database_type& database () const; private: template 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 p_; mutable lazy_ptr_impl i_; }; #endif #ifdef ODB_CXX11 // C++11 std::unique_ptr lazy version. // template > class lazy_unique_ptr { // Standard lazy_unique_ptr interface. // public: typedef T* pointer; // For now assume it is T*. typedef T element_type; typedef D deleter_type; /*constexpr*/ lazy_unique_ptr () /*noexcept*/; #ifdef ODB_CXX11_NULLPTR /*constexpr*/ lazy_unique_ptr (std::nullptr_t) /*noexcept*/; #endif explicit lazy_unique_ptr (pointer) /*noexcept*/; // For now assume D is non-reference. // lazy_unique_ptr (pointer, const deleter_type&) /*noexcept*/; lazy_unique_ptr (pointer, deleter_type&&) /*noexcept*/; lazy_unique_ptr (lazy_unique_ptr&&) /*noexcept*/; template lazy_unique_ptr (lazy_unique_ptr&&) /*noexcept*/; //template lazy_unique_ptr (std::auto_ptr&&) /*noexcept*/; #ifdef ODB_CXX11_NULLPTR lazy_unique_ptr& operator= (std::nullptr_t) /*noexcept*/; #endif lazy_unique_ptr& operator= (lazy_unique_ptr&&) /*noexcept*/; template lazy_unique_ptr& operator= (lazy_unique_ptr&&) /*noexcept*/; T& operator* () const; pointer operator-> () const /*noexcept*/; pointer get () const /*noexcept*/; #ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR explicit operator bool() const /*noexcept*/; #else typedef std::unique_ptr lazy_unique_ptr::*unspecified_bool_type; operator unspecified_bool_type () const { return (p_ || i_) ? &lazy_unique_ptr::p_ : 0; } #endif pointer release () /*noexcept*/; void reset (pointer = pointer ()) /*noexcept*/; void swap (lazy_unique_ptr&) /*noexcept*/; deleter_type& get_deleter () /*noexcept*/; const deleter_type& get_deleter () const /*noexcept*/; #ifdef ODB_CXX11_DELETED_FUNCTION lazy_unique_ptr (const lazy_unique_ptr&) = delete; lazy_unique_ptr& operator= (const lazy_unique_ptr&) = delete; #else private: lazy_unique_ptr (const lazy_unique_ptr&); lazy_unique_ptr& operator= (const lazy_unique_ptr&); #endif // Initialization/assignment from unique_ptr. // public: template lazy_unique_ptr (std::unique_ptr&&) /*noexcept*/; template lazy_unique_ptr& operator= (std::unique_ptr&&) /*noexcept*/; // Lazy loading interface. // public: typedef odb::database database_type; // NULL loaded() // // true true NULL pointer to transient object // false true valid pointer to persistent object // true false unloaded pointer to persistent object // false false valid pointer to transient object // bool loaded () const; std::unique_ptr& load () const; // Unload the pointer. For transient objects this function is // equivalent to reset(). // void unload () const; // Get the underlying eager pointer. If this is an unloaded pointer // to a persistent object, then the returned pointer will be NULL. // std::unique_ptr& get_eager () const; template lazy_unique_ptr (DB&, const ID&); template lazy_unique_ptr (DB&, pointer); template lazy_unique_ptr (DB&, pointer, const deleter_type&); template lazy_unique_ptr (DB&, pointer, deleter_type&&); template lazy_unique_ptr (DB&, std::unique_ptr&&); //template lazy_unique_ptr (DB&, std::auto_ptr&&); template void reset (DB&, const ID&); template void reset (DB&, pointer); template void reset (DB&, std::unique_ptr&&); //template void reset (DB&, std::auto_ptr&&); #ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT template #else template #endif typename object_traits::id_type object_id () const; database_type& database () const; // Helpers. // public: template bool equal (const lazy_unique_ptr&) const; private: template friend class lazy_unique_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 // unique_ptr reference returned by load() is transferred to // another pointer or reset. // mutable std::unique_ptr p_; mutable lazy_ptr_impl i_; }; template void swap (lazy_unique_ptr&, lazy_unique_ptr&) /*noexcept*/; // operator< and operator<< are not provided. // template bool operator== (const lazy_unique_ptr&, const lazy_unique_ptr&); template bool operator!= (const lazy_unique_ptr&, const lazy_unique_ptr&); #ifdef ODB_CXX11_NULLPTR template bool operator== (const lazy_unique_ptr&, std::nullptr_t) /*noexcept*/; template bool operator== (std::nullptr_t, const lazy_unique_ptr&) /*noexcept*/; template bool operator!= (const lazy_unique_ptr&, std::nullptr_t) /*noexcept*/; template bool operator!= (std::nullptr_t, const lazy_unique_ptr&) /*noexcept*/; #endif // C++11 std::shared_ptr lazy version. // template class lazy_weak_ptr; template class lazy_shared_ptr { // The standard shared_ptr interface. // public: typedef T element_type; /*constexpr*/ lazy_shared_ptr () /*noexcept*/; #ifdef ODB_CXX11_NULLPTR /*constexpr*/ lazy_shared_ptr (std::nullptr_t) /*noexcept*/; #endif template explicit lazy_shared_ptr (Y*); template lazy_shared_ptr (Y*, D); template lazy_shared_ptr (Y*, D, A); #ifdef ODB_CXX11_NULLPTR template lazy_shared_ptr (std::nullptr_t, D); template lazy_shared_ptr (std::nullptr_t, D, A); #endif template lazy_shared_ptr (const lazy_shared_ptr&, T*) /*noexcept*/; lazy_shared_ptr (const lazy_shared_ptr&) /*noexcept*/; template lazy_shared_ptr (const lazy_shared_ptr&) /*noexcept*/; lazy_shared_ptr (lazy_shared_ptr&&) /*noexcept*/; template lazy_shared_ptr (lazy_shared_ptr&&) /*noexcept*/; template explicit lazy_shared_ptr (const lazy_weak_ptr&); //template explicit lazy_shared_ptr (std::auto_ptr&&); template lazy_shared_ptr (std::unique_ptr&&); ~lazy_shared_ptr (); lazy_shared_ptr& operator= (const lazy_shared_ptr&) /*noexcept*/; template lazy_shared_ptr& operator= (const lazy_shared_ptr&) /*noexcept*/; lazy_shared_ptr& operator= (lazy_shared_ptr&&) /*noexcept*/; template lazy_shared_ptr& operator= (lazy_shared_ptr&&) /*noexcept*/; //template lazy_shared_ptr& operator= (std::auto_ptr&&); template lazy_shared_ptr& operator= (std::unique_ptr&&); void swap (lazy_shared_ptr&) /*noexcept*/; void reset () /*noexcept*/; template void reset (Y*); template void reset (Y*, D); template void reset (Y*, D, A); T* get () const /*noexcept*/; T& operator* () const /*noexcept*/; T* operator-> () const /*noexcept*/; long use_count () const /*noexcept*/; bool unique () const /*noexcept*/; #ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR explicit operator bool () const /*noexcept*/; #else typedef std::shared_ptr lazy_shared_ptr::*unspecified_bool_type; operator unspecified_bool_type () const { return (p_ || i_) ? &lazy_shared_ptr::p_ : 0; } #endif // owner_before () is not provded. // Initialization/assignment from shared_ptr and weak_ptr. // public: template lazy_shared_ptr (const std::shared_ptr&); template lazy_shared_ptr (std::shared_ptr&&); template explicit lazy_shared_ptr (const std::weak_ptr&); template lazy_shared_ptr& operator= (const std::shared_ptr&); template lazy_shared_ptr& operator= (std::shared_ptr&&); // Lazy loading interface. // public: typedef odb::database database_type; // NULL loaded() // // true true NULL pointer to transient object // false true valid pointer to persistent object // true false unloaded pointer to persistent object // false false valid pointer to transient object // bool loaded () const; std::shared_ptr load () const; // Unload the pointer. For transient objects this function is // equivalent to reset(). // void unload () const; // Get the underlying eager pointer. If this is an unloaded pointer // to a persistent object, then the returned pointer will be NULL. // std::shared_ptr get_eager () const; template lazy_shared_ptr (DB&, const ID&); template lazy_shared_ptr (DB&, Y*); template lazy_shared_ptr (DB&, Y*, D); template lazy_shared_ptr (DB&, Y*, D, A); //template lazy_shared_ptr (DB&, std::auto_ptr&&); template lazy_shared_ptr (DB&, const std::shared_ptr&); template lazy_shared_ptr (DB&, std::shared_ptr&&); template lazy_shared_ptr (DB&, const std::weak_ptr&); template void reset (DB&, const ID&); template void reset (DB&, Y*); template void reset (DB&, Y*, D); template void reset (DB&, Y*, D, A); //template void reset (DB&, std::auto_ptr&&); template void reset (DB&, const std::shared_ptr&); template void reset (DB&, std::shared_ptr&&); #ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT template #else template #endif typename object_traits::id_type object_id () const; database_type& database () const; // Helpers. // public: template bool equal (const lazy_shared_ptr&) const; private: template friend class lazy_shared_ptr; template friend class lazy_weak_ptr; // For lazy_weak_ptr::lock(). // lazy_shared_ptr (std::shared_ptr&& p, const lazy_ptr_impl& i) : p_ (std::move (p)), i_ (i) {} private: mutable std::shared_ptr p_; mutable lazy_ptr_impl i_; }; template void swap (lazy_shared_ptr&, lazy_shared_ptr&) /*noexcept*/; template D* get_deleter (const lazy_shared_ptr&) /*noexcept*/; // operator< and operator<< are not provided. // template bool operator== (const lazy_shared_ptr&, const lazy_shared_ptr&) /*noexcept*/; template bool operator!= (const lazy_shared_ptr&, const lazy_shared_ptr&) /*noexcept*/; #ifdef ODB_CXX11_NULLPTR template bool operator== (const lazy_shared_ptr&, std::nullptr_t) /*noexcept*/; template bool operator== (std::nullptr_t, const lazy_shared_ptr&) /*noexcept*/; template bool operator!= (const lazy_shared_ptr&, std::nullptr_t) /*noexcept*/; template bool operator!= (std::nullptr_t, const lazy_shared_ptr&) /*noexcept*/; #endif // C++11 std::weak_ptr lazy version. // template class lazy_weak_ptr { // The standard weak_ptr interface. // public: typedef T element_type; /*constexpr*/ lazy_weak_ptr () /*noexcept*/; template lazy_weak_ptr (const lazy_shared_ptr&) /*noexcept*/; lazy_weak_ptr (const lazy_weak_ptr&) /*noexcept*/; template lazy_weak_ptr (const lazy_weak_ptr&) /*noexcept*/; ~lazy_weak_ptr (); lazy_weak_ptr& operator= (const lazy_weak_ptr&) /*noexcept*/; template lazy_weak_ptr& operator= (const lazy_weak_ptr&) /*noexcept*/; template lazy_weak_ptr& operator= (const lazy_shared_ptr&) /*noexcept*/; void swap (lazy_weak_ptr&) /*noexcept*/; void reset () /*noexcept*/; long use_count () const /*noexcept*/; bool expired () const /*noexcept*/; lazy_shared_ptr lock () const /*noexcept*/; // owner_before () is not provded. // Initialization/assignment from shared_ptr and weak_ptr. // public: template lazy_weak_ptr (const std::weak_ptr&); template lazy_weak_ptr (const std::shared_ptr&); template lazy_weak_ptr& operator= (const std::weak_ptr&); template lazy_weak_ptr& operator= (const std::shared_ptr&); // 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 transient object // bool loaded () const; // Performs both lock and load. // std::shared_ptr load () const; // Unload the pointer. For transient objects this function is // equivalent to reset(). // void unload () const; // Get the underlying eager pointer. If this is an unloaded pointer // to a persistent object, then the returned pointer will be NULL. // std::weak_ptr get_eager () const; template lazy_weak_ptr (DB&, const ID&); template lazy_weak_ptr (DB&, const std::shared_ptr&); template lazy_weak_ptr (DB&, const std::weak_ptr&); template void reset (DB&, const ID&); template void reset (DB&, const std::shared_ptr&); template void reset (DB&, const std::weak_ptr&); // The object_id() function can only be called when the object is // persistent, or: expired() XOR loaded() (can use != for XOR). // #ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT template #else template #endif typename object_traits::id_type object_id () const; database_type& database () const; private: template friend class lazy_shared_ptr; template friend class lazy_weak_ptr; mutable std::weak_ptr p_; mutable lazy_ptr_impl i_; }; // operator< is not provided. // template void swap (lazy_weak_ptr&, lazy_weak_ptr&); #endif // ODB_CXX11 namespace common { using odb::lazy_ptr; #ifndef ODB_CXX11 using odb::lazy_auto_ptr; #endif #ifdef ODB_CXX11 using odb::lazy_unique_ptr; using odb::lazy_shared_ptr; using odb::lazy_weak_ptr; #endif } } #include #include #include #include #endif // ODB_LAZY_PTR_HXX