aboutsummaryrefslogtreecommitdiff
path: root/common/session/custom/session.hxx
blob: bb60a4b685265b922c783f0561e98789bcacb582 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// file      : common/session/custom/session.hxx
// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
// 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/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&);

  // Current session interface.
  //
public:
  static bool
  has_current ();

  static session&
  current ();

  // Change tracking interface.
  //
  // Call flush() within a transaction to apply the changes to the
  // database. Then after successfully committing the transaction,
  // call mark() to mark all the changed objects as again unchanged.
  //
public:
  void
  flush (odb::database&);

  void
  mark ();

private:
  struct object_map_base
  {
    virtual
    ~object_map_base () {}

    virtual void
    flush (odb::database&) = 0;

    virtual void
    mark () = 0;
  };

  template <typename T>
  struct object_state
  {
    typedef typename odb::object_traits<T>::pointer_type pointer_type;

    explicit
    object_state (pointer_type o): obj (o), flushed_ (false) {}

    pointer_type obj;
    pointer_type orig;
    bool flushed_;
  };

  template <typename T>
  struct object_map: object_map_base,
                     std::map<typename odb::object_traits<T>::id_type,
                              object_state<T> >
  {
    virtual void
    flush (odb::database&);

    virtual void
    mark ();
  };

  // Object cache interface.
  //
public:
  template <typename T>
  struct position
  {
    typedef object_map<T> map;
    typedef typename map::iterator iterator;

    position () {}
    position (map& m, const iterator& p): map_ (&m), pos_ (p) {}

    map* map_;
    iterator pos_;
  };

  template <typename T>
  position<T>
  insert (odb::database&,
          const typename odb::object_traits<T>::id_type&,
          const typename odb::object_traits<T>::pointer_type&);

  template <typename T>
  static void
  initialize (const position<T>&);

  template <typename T>
  typename odb::object_traits<T>::pointer_type
  find (odb::database&, const typename odb::object_traits<T>::id_type&) const;

  template <typename T>
  void
  erase (odb::database&, const typename odb::object_traits<T>::id_type&);

  template <typename T>
  static void
  erase (const position<T>& p)
  {
    p.map_->erase (p.pos_);
  }

private:
  typedef std::map<const std::type_info*,
                   std::shared_ptr<object_map_base>,
                   odb::details::type_info_comparator> type_map;
  type_map map_;
};

#include "session.txx"

#endif // SESSION_HXX