From 2bf2944a844d002267d3508ce81a2128ccbb8af7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 9 Nov 2015 18:14:37 +0200 Subject: Make database class move-constructible This means it can be returned by value from a function in C++11. --- odb/sqlite/connection-factory.cxx | 86 +++++++++++++++++++-------------------- odb/sqlite/connection-factory.hxx | 46 ++++----------------- odb/sqlite/connection.cxx | 32 +++++++++++---- odb/sqlite/connection.hxx | 42 ++++++++++++++----- odb/sqlite/connection.ixx | 6 +++ odb/sqlite/database.hxx | 9 ++++ odb/sqlite/database.ixx | 16 ++++++++ 7 files changed, 136 insertions(+), 101 deletions(-) diff --git a/odb/sqlite/connection-factory.cxx b/odb/sqlite/connection-factory.cxx index c40190a..317d048 100644 --- a/odb/sqlite/connection-factory.cxx +++ b/odb/sqlite/connection-factory.cxx @@ -18,15 +18,6 @@ namespace odb namespace sqlite { // - // connection_factory - // - - connection_factory:: - ~connection_factory () - { - } - - // // single_connection_factory // @@ -43,14 +34,14 @@ namespace odb single_connection_factory:: create () { - return single_connection_ptr (new (shared) single_connection (*db_)); + return single_connection_ptr (new (shared) single_connection (*this)); } connection_ptr single_connection_factory:: connect () { mutex_.lock (); - connection_->factory_ = this; + connection_->callback_ = &connection_->cb_; connection_ptr r (connection_); connection_.reset (); return r; @@ -59,14 +50,16 @@ namespace odb void single_connection_factory:: database (database_type& db) { - db_ = &db; - connection_ = create (); + connection_factory::database (db); + + if (!connection_) + connection_ = create (); } bool single_connection_factory:: release (single_connection* c) { - c->factory_ = 0; + c->callback_ = 0; connection_.reset (inc_ref (c)); connection_->recycle (); mutex_.unlock (); @@ -78,28 +71,26 @@ namespace odb // single_connection_factory::single_connection:: - single_connection (database_type& db, int extra_flags) - : connection (db, extra_flags), factory_ (0) + single_connection (single_connection_factory& f, int extra_flags) + : connection (f, extra_flags) { - callback_.arg = this; - callback_.zero_counter = &zero_counter; - shared_base::callback_ = &callback_; + cb_.arg = this; + cb_.zero_counter = &zero_counter; } single_connection_factory::single_connection:: - single_connection (database_type& db, sqlite3* handle) - : connection (db, handle), factory_ (0) + single_connection (single_connection_factory& f, sqlite3* handle) + : connection (f, handle) { - callback_.arg = this; - callback_.zero_counter = &zero_counter; - shared_base::callback_ = &callback_; + cb_.arg = this; + cb_.zero_counter = &zero_counter; } bool single_connection_factory::single_connection:: zero_counter (void* arg) { single_connection* c (static_cast (arg)); - return c->factory_ ? c->factory_->release (c) : true; + return static_cast (c->factory_).release (c); } // @@ -109,14 +100,18 @@ namespace odb connection_ptr new_connection_factory:: connect () { - return connection_ptr ( - new (shared) connection (*db_, extra_flags_)); + return connection_ptr (new (shared) connection (*this, extra_flags_)); } void new_connection_factory:: database (database_type& db) { - db_ = &db; + bool first (db_ == 0); + + connection_factory::database (db); + + if (!first) + return; // Unless explicitly disabled, enable shared cache. // @@ -134,7 +129,7 @@ namespace odb create () { return pooled_connection_ptr ( - new (shared) pooled_connection (*db_, extra_flags_)); + new (shared) pooled_connection (*this, extra_flags_)); } connection_pool_factory:: @@ -165,7 +160,7 @@ namespace odb shared_ptr c (connections_.back ()); connections_.pop_back (); - c->pool_ = this; + c->callback_ = &c->cb_; in_use_++; return c; } @@ -175,7 +170,7 @@ namespace odb if(max_ == 0 || in_use_ < max_) { shared_ptr c (create ()); - c->pool_ = this; + c->callback_ = &c->cb_; in_use_++; return c; } @@ -191,7 +186,12 @@ namespace odb void connection_pool_factory:: database (database_type& db) { - db_ = &db; + bool first (db_ == 0); + + connection_factory::database (db); + + if (!first) + return; // Unless explicitly disabled, enable shared cache. // @@ -212,7 +212,7 @@ namespace odb bool connection_pool_factory:: release (pooled_connection* c) { - c->pool_ = 0; + c->callback_ = 0; lock l (mutex_); @@ -241,28 +241,26 @@ namespace odb // connection_pool_factory::pooled_connection:: - pooled_connection (database_type& db, int extra_flags) - : connection (db, extra_flags), pool_ (0) + pooled_connection (connection_pool_factory& f, int extra_flags) + : connection (f, extra_flags) { - callback_.arg = this; - callback_.zero_counter = &zero_counter; - shared_base::callback_ = &callback_; + cb_.arg = this; + cb_.zero_counter = &zero_counter; } connection_pool_factory::pooled_connection:: - pooled_connection (database_type& db, sqlite3* handle) - : connection (db, handle), pool_ (0) + pooled_connection (connection_pool_factory& f, sqlite3* handle) + : connection (f, handle) { - callback_.arg = this; - callback_.zero_counter = &zero_counter; - shared_base::callback_ = &callback_; + cb_.arg = this; + cb_.zero_counter = &zero_counter; } bool connection_pool_factory::pooled_connection:: zero_counter (void* arg) { pooled_connection* c (static_cast (arg)); - return c->pool_ ? c->pool_->release (c) : true; + return static_cast (c->factory_).release (c); } } } diff --git a/odb/sqlite/connection-factory.hxx b/odb/sqlite/connection-factory.hxx index c0d15ff..d3d6aea 100644 --- a/odb/sqlite/connection-factory.hxx +++ b/odb/sqlite/connection-factory.hxx @@ -24,29 +24,13 @@ namespace odb { namespace sqlite { - class LIBODB_SQLITE_EXPORT connection_factory - { - public: - virtual connection_ptr - connect () = 0; - - public: - typedef sqlite::database database_type; - - virtual void - database (database_type&) = 0; - - virtual - ~connection_factory (); - }; - // Share a single connection. // class LIBODB_SQLITE_EXPORT single_connection_factory: public connection_factory { public: - single_connection_factory (): db_ (0) {} + single_connection_factory () {} virtual connection_ptr connect (); @@ -65,8 +49,8 @@ namespace odb class LIBODB_SQLITE_EXPORT single_connection: public connection { public: - single_connection (database_type&, int extra_flags = 0); - single_connection (database_type&, sqlite3*); + single_connection (single_connection_factory&, int extra_flags = 0); + single_connection (single_connection_factory&, sqlite3*); private: static bool @@ -74,12 +58,7 @@ namespace odb private: friend class single_connection_factory; - - shared_base::refcount_callback callback_; - - // NULL factory value indicates that the connection is not in use. - // - single_connection_factory* factory_; + shared_base::refcount_callback cb_; }; friend class single_connection; @@ -99,7 +78,6 @@ namespace odb release (single_connection*); protected: - database_type* db_; details::mutex mutex_; single_connection_ptr connection_; }; @@ -110,7 +88,7 @@ namespace odb public connection_factory { public: - new_connection_factory (): db_ (0), extra_flags_ (0) {} + new_connection_factory (): extra_flags_ (0) {} virtual connection_ptr connect (); @@ -123,7 +101,6 @@ namespace odb new_connection_factory& operator= (const new_connection_factory&); private: - database_type* db_; int extra_flags_; }; @@ -156,7 +133,6 @@ namespace odb extra_flags_ (0), in_use_ (0), waiters_ (0), - db_ (0), cond_ (mutex_) { // max_connections == 0 means unlimited. @@ -181,8 +157,8 @@ namespace odb class LIBODB_SQLITE_EXPORT pooled_connection: public connection { public: - pooled_connection (database_type&, int extra_flags = 0); - pooled_connection (database_type&, sqlite3*); + pooled_connection (connection_pool_factory&, int extra_flags = 0); + pooled_connection (connection_pool_factory&, sqlite3*); private: static bool @@ -190,12 +166,7 @@ namespace odb private: friend class connection_pool_factory; - - shared_base::refcount_callback callback_; - - // NULL pool value indicates that the connection is not in use. - // - connection_pool_factory* pool_; + shared_base::refcount_callback cb_; }; friend class pooled_connection; @@ -223,7 +194,6 @@ namespace odb std::size_t in_use_; // Number of connections currently in use. std::size_t waiters_; // Number of threads waiting for a connection. - database_type* db_; connections connections_; details::mutex mutex_; diff --git a/odb/sqlite/connection.cxx b/odb/sqlite/connection.cxx index c44d648..b150470 100644 --- a/odb/sqlite/connection.cxx +++ b/odb/sqlite/connection.cxx @@ -29,12 +29,13 @@ namespace odb namespace sqlite { connection:: - connection (database_type& db, int extra_flags) - : odb::connection (db), - db_ (db), + connection (connection_factory& cf, int extra_flags) + : odb::connection (cf), unlock_cond_ (unlock_mutex_), active_objects_ (0) { + database_type& db (database ()); + int f (db.flags () | extra_flags); const string& n (db.name ()); @@ -81,9 +82,8 @@ namespace odb } connection:: - connection (database_type& db, sqlite3* handle) - : odb::connection (db), - db_ (db), + connection (connection_factory& cf, sqlite3* handle) + : odb::connection (cf), handle_ (handle), unlock_cond_ (unlock_mutex_), active_objects_ (0) @@ -94,14 +94,16 @@ namespace odb void connection:: init () { + database_type& db (database ()); + // Enable/disable foreign key constraints. // generic_statement st ( *this, - db_.foreign_keys () + db.foreign_keys () ? "PRAGMA foreign_keys=ON" : "PRAGMA foreign_keys=OFF", - db_.foreign_keys () ? 22 : 23); + db.foreign_keys () ? 22 : 23); st.execute (); // Create statement cache. @@ -190,6 +192,20 @@ namespace odb while (active_objects_ != 0) active_objects_->clear (); } + + // connection_factory + // + connection_factory:: + ~connection_factory () + { + } + + void connection_factory:: + database (database_type& db) + { + odb::connection_factory::db_ = &db; + db_ = &db; + } } } diff --git a/odb/sqlite/connection.hxx b/odb/sqlite/connection.hxx index 7499eb9..5110163 100644 --- a/odb/sqlite/connection.hxx +++ b/odb/sqlite/connection.hxx @@ -30,6 +30,7 @@ namespace odb namespace sqlite { class statement_cache; + class connection_factory; class connection; typedef details::shared_ptr connection_ptr; @@ -76,14 +77,11 @@ namespace odb virtual ~connection (); - connection (database_type&, int extra_flags = 0); - connection (database_type&, sqlite3* handle); + connection (connection_factory&, int extra_flags = 0); + connection (connection_factory&, sqlite3* handle); database_type& - database () - { - return db_; - } + database (); public: virtual transaction_impl* @@ -173,11 +171,6 @@ namespace odb init (); private: - // Needed to break the circular connection-database dependency - // (odb::connection has the odb::database member). - // - database_type& db_; - auto_handle handle_; // Keep statement_cache_ after handle_ so that it is destroyed before @@ -205,6 +198,33 @@ namespace odb friend class active_object; active_object* active_objects_; }; + + class LIBODB_SQLITE_EXPORT connection_factory: + public odb::connection_factory + { + public: + typedef sqlite::database database_type; + + virtual void + database (database_type&); + + database_type& + database () {return *db_;} + + virtual connection_ptr + connect () = 0; + + virtual + ~connection_factory (); + + connection_factory (): db_ (0) {} + + // Needed to break the circular connection_factory-database dependency + // (odb::connection_factory has the odb::database member). + // + protected: + database_type* db_; + }; } } diff --git a/odb/sqlite/connection.ixx b/odb/sqlite/connection.ixx index 23df27c..ab6d72e 100644 --- a/odb/sqlite/connection.ixx +++ b/odb/sqlite/connection.ixx @@ -32,6 +32,12 @@ namespace odb // connection // + inline database& connection:: + database () + { + return static_cast (factory_).database (); + } + template inline prepared_query connection:: prepare_query (const char* n, const char* q) diff --git a/odb/sqlite/database.hxx b/odb/sqlite/database.hxx index f7f3994..f846f9e 100644 --- a/odb/sqlite/database.hxx +++ b/odb/sqlite/database.hxx @@ -14,6 +14,7 @@ #include // std::ostream #include +#include // ODB_CXX11 #include #include @@ -84,6 +85,12 @@ namespace odb details::transfer_ptr = details::transfer_ptr ()); + // Move-constructible but not move-assignable. + // +#ifdef ODB_CXX11 + database (database&&); +#endif + static void print_usage (std::ostream&); @@ -458,6 +465,8 @@ namespace odb connection_ (); private: + // Note: remember to update move ctor if adding any new members. + // std::string name_; int flags_; bool foreign_keys_; diff --git a/odb/sqlite/database.ixx b/odb/sqlite/database.ixx index c1e8f07..aec4ba5 100644 --- a/odb/sqlite/database.ixx +++ b/odb/sqlite/database.ixx @@ -2,12 +2,28 @@ // copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file +#include // move() + #include namespace odb { namespace sqlite { +#ifdef ODB_CXX11 + inline database:: + database (database&& db) // Has to be inline. + : odb::database (std::move (db)), + name_ (std::move (db.name_)), + flags_ (db.flags_), + foreign_keys_ (db.foreign_keys_), + vfs_ (std::move (db.vfs_)), + factory_ (std::move (db.factory_)) + { + factory_->database (*this); // New database instance. + } +#endif + inline connection_ptr database:: connection () { -- cgit v1.1