aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-06-18 09:32:09 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-06-18 09:32:09 +0200
commitd654146abfd45870c9bb0c1a5779d51b0aff2973 (patch)
treec11673177dcaf5f8e6f2584b84415a96461daba8
parent51c80ddaaaa7ddd1bd3708dc36289e322f30939e (diff)
Allocate container traits lazily and only when their definition is seen
This fixes a problem with polymorphic hierarchies spread over multiple files in which case the source code for the derived class does not have the definition of the container traits for the base class. See the comment in the source code for further details.
-rw-r--r--odb/pgsql/polymorphic-object-statements.hxx5
-rw-r--r--odb/pgsql/polymorphic-object-statements.txx1
-rw-r--r--odb/pgsql/simple-object-statements.hxx57
-rw-r--r--odb/pgsql/simple-object-statements.txx1
4 files changed, 58 insertions, 6 deletions
diff --git a/odb/pgsql/polymorphic-object-statements.hxx b/odb/pgsql/polymorphic-object-statements.hxx
index 43dd55e..8a85e3c 100644
--- a/odb/pgsql/polymorphic-object-statements.hxx
+++ b/odb/pgsql/polymorphic-object-statements.hxx
@@ -378,7 +378,7 @@ namespace odb
container_statement_cache_type&
container_statment_cache ()
{
- return container_statement_cache_;
+ return container_statement_cache_.get (conn_);
}
public:
@@ -410,7 +410,8 @@ namespace odb
root_statements_type& root_statements_;
base_statements_type& base_statements_;
- container_statement_cache_type container_statement_cache_;
+ container_statement_cache_ptr<container_statement_cache_type>
+ container_statement_cache_;
image_type image_;
diff --git a/odb/pgsql/polymorphic-object-statements.txx b/odb/pgsql/polymorphic-object-statements.txx
index 2f10b22..2a3ad7a 100644
--- a/odb/pgsql/polymorphic-object-statements.txx
+++ b/odb/pgsql/polymorphic-object-statements.txx
@@ -81,7 +81,6 @@ namespace odb
: statements_base (conn),
root_statements_ (conn.statement_cache ().find_object<root_type> ()),
base_statements_ (conn.statement_cache ().find_object<base_type> ()),
- container_statement_cache_ (conn),
insert_image_binding_ (insert_image_bind_, insert_column_count),
insert_image_native_binding_ (insert_image_values_,
insert_image_lengths_,
diff --git a/odb/pgsql/simple-object-statements.hxx b/odb/pgsql/simple-object-statements.hxx
index e6de345..cba8598 100644
--- a/odb/pgsql/simple-object-statements.hxx
+++ b/odb/pgsql/simple-object-statements.hxx
@@ -29,6 +29,58 @@ namespace odb
{
namespace pgsql
{
+ // The container_statement_cache class is only defined (and used) in
+ // the generated source file. However, object_statements may be
+ // referenced from another source file in the case of a polymorphic
+ // hierarchy (though in this case the container statement cache is
+ // not used). As a result, we cannot have a by-value member and
+ // instead will store a pointer and lazily allocate the cache if
+ // and when needed. We will also need to store a pointer to the
+ // deleter function which will be initialized during allocation
+ // (at that point we know that the cache class is defined).
+ //
+ template <typename T>
+ struct container_statement_cache_ptr
+ {
+ typedef pgsql::connection connection_type;
+
+ container_statement_cache_ptr (): p_ (0) {}
+ ~container_statement_cache_ptr () {if (p_ != 0) (this->*deleter_) (0);}
+
+ T&
+ get (connection_type& c)
+ {
+ if (p_ == 0)
+ allocate (&c);
+
+ return *p_;
+ }
+
+ private:
+ void
+ allocate (connection_type*);
+
+ private:
+ T* p_;
+ void (container_statement_cache_ptr::*deleter_) (connection_type*);
+ };
+
+ template <typename T>
+ void container_statement_cache_ptr<T>::
+ allocate (connection_type* c)
+ {
+ // To reduce object code size, this function acts as both allocator
+ // and deleter.
+ //
+ if (p_ == 0)
+ {
+ p_ = new T (*c);
+ deleter_ = &container_statement_cache_ptr<T>::allocate;
+ }
+ else
+ delete p_;
+ }
+
//
// Implementation for objects with object id.
//
@@ -380,7 +432,7 @@ namespace odb
container_statement_cache_type&
container_statment_cache ()
{
- return container_statement_cache_;
+ return container_statement_cache_.get (conn_);
}
public:
@@ -416,7 +468,8 @@ namespace odb
clear_delayed_ ();
protected:
- container_statement_cache_type container_statement_cache_;
+ container_statement_cache_ptr<container_statement_cache_type>
+ container_statement_cache_;
image_type image_;
diff --git a/odb/pgsql/simple-object-statements.txx b/odb/pgsql/simple-object-statements.txx
index 1fcd104..fe9fe9b 100644
--- a/odb/pgsql/simple-object-statements.txx
+++ b/odb/pgsql/simple-object-statements.txx
@@ -46,7 +46,6 @@ namespace odb
object_statements<T>::
object_statements (connection_type& conn)
: object_statements_base (conn),
- container_statement_cache_ (conn),
// select
select_image_binding_ (select_image_bind_, select_column_count),
// insert