diff options
Diffstat (limited to 'odb-tests/common/session/custom/session.hxx')
-rw-r--r-- | odb-tests/common/session/custom/session.hxx | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/odb-tests/common/session/custom/session.hxx b/odb-tests/common/session/custom/session.hxx new file mode 100644 index 0000000..2d2f597 --- /dev/null +++ b/odb-tests/common/session/custom/session.hxx @@ -0,0 +1,191 @@ +// file : common/session/custom/session.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef SESSION_HXX +#define SESSION_HXX + +#include <map> +#include <memory> +#include <typeinfo> + +#include <odb/database.hxx> +#include <odb/transaction.hxx> + +#include <odb/traits.hxx> // odb::object_traits +#include <odb/details/type-info.hxx> // odb::details::type_info_comparator + +// This custom session implementation assumes we are working with +// one database at a time. +// +class session +{ +public: + session (); + ~session (); + +private: + session (const session&); + session& operator= (const session&); + + // Session for the current thread. This can be implemented in pretty + // much any way that makes sense to the application. It can be a global + // session as we have here. In multi-threaded applications we could use + // TLS instead. + // +public: + static session* current; + + // Change tracking interface. + // +public: + // Call flush() within a transaction to apply the changes to the + // database. + // + void + flush (odb::database&); + +private: + struct object_map_base + { + virtual + ~object_map_base () {} + + // Return true if we flushed anything. + // + virtual bool + flush (odb::database&) = 0; + + virtual void + mark (unsigned short event) = 0; + }; + + enum object_state + { + tracking, // Tracking any modifications by storing the original copy. + changed, // Known to be changed. + flushed // Flushed but not yet committed/rolled back. + }; + + template <typename T> + struct object_data + { + typedef typename odb::object_traits<T>::pointer_type pointer_type; + + explicit + object_data (pointer_type o): obj (o), state (tracking) {} + + pointer_type obj; + pointer_type orig; + object_state state; + }; + + template <typename T> + struct object_map: object_map_base, + std::map<typename odb::object_traits<T>::id_type, + object_data<T> > + { + virtual bool + flush (odb::database&); + + virtual void + mark (unsigned short event); + }; + + // Object cache interface. + // +public: + static bool + _has_cache () {return current != 0;} + + template <typename T> + struct cache_position + { + typedef object_map<T> map; + typedef typename map::iterator iterator; + + cache_position (): map_ (0) {} + cache_position (map& m, const iterator& p): map_ (&m), pos_ (p) {} + + cache_position (const cache_position& p) + : map_ (p.map_) + { + // It might not be ok to use an uninitialized iterator. + // + if (p.map_ != 0) + pos_ = p.pos_; + } + + cache_position& + operator= (const cache_position& p) + { + // It might not be ok to use an uninitialized iterator on the rhs. + // + if (p.map_ != 0) + pos_ = p.pos_; + map_ = p.map_; + return *this; + } + + map* map_; + iterator pos_; + }; + + // Cache management. + // + template <typename T> + static cache_position<T> + _cache_insert (odb::database&, + const typename odb::object_traits<T>::id_type&, + const typename odb::object_traits<T>::pointer_type&); + + template <typename T> + static typename odb::object_traits<T>::pointer_type + _cache_find (odb::database&, const typename odb::object_traits<T>::id_type&); + + template <typename T> + static void + _cache_erase (const cache_position<T>& p) + { + if (p.map_ != 0) + p.map_->erase (p.pos_); + } + + // Notifications. + // + template <typename T> + static void + _cache_persist (const cache_position<T>& p) + { + _cache_load (p); + } + + template <typename T> + static void + _cache_load (const cache_position<T>&); + + template <typename T> + static void + _cache_update (odb::database&, const T&); + + template <typename T> + static void + _cache_erase (odb::database&, + const typename odb::object_traits<T>::id_type&); + +private: + // Post-commit/rollback callback. + // + static void + mark (unsigned short event, void* key, unsigned long long); + +private: + typedef std::map<const std::type_info*, + std::shared_ptr<object_map_base>, + odb::details::type_info_comparator> type_map; + type_map map_; + odb::transaction* tran_; +}; + +#include "session.txx" + +#endif // SESSION_HXX |