From fc70be62d8698496a20b6947d102757f426c5b3e 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/pgsql/connection-factory.cxx | 56 ++++++++++++++-------------------------- odb/pgsql/connection-factory.hxx | 39 +++------------------------- odb/pgsql/connection.cxx | 23 ++++++++++++++--- odb/pgsql/connection.hxx | 42 ++++++++++++++++++++++-------- odb/pgsql/connection.ixx | 6 +++++ odb/pgsql/database.hxx | 9 +++++++ odb/pgsql/database.ixx | 20 ++++++++++++++ 7 files changed, 109 insertions(+), 86 deletions(-) diff --git a/odb/pgsql/connection-factory.cxx b/odb/pgsql/connection-factory.cxx index f35b2c8..a57fc41 100644 --- a/odb/pgsql/connection-factory.cxx +++ b/odb/pgsql/connection-factory.cxx @@ -15,39 +15,20 @@ namespace odb namespace pgsql { - // - // connection_factory - // - - connection_factory:: - ~connection_factory () - { - } - - // // new_connection_factory // - connection_ptr new_connection_factory:: connect () { - return connection_ptr (new (shared) connection (*db_)); + return connection_ptr (new (shared) connection (*this)); } - void new_connection_factory:: - database (database_type& db) - { - db_ = &db; - } - - // // connection_pool_factory // - connection_pool_factory::pooled_connection_ptr connection_pool_factory:: create () { - return pooled_connection_ptr (new (shared) pooled_connection (*db_)); + return pooled_connection_ptr (new (shared) pooled_connection (*this)); } connection_pool_factory:: @@ -79,7 +60,7 @@ namespace odb shared_ptr c (connections_.back ()); connections_.pop_back (); - c->pool_ = this; + c->callback_ = &c->cb_; in_use_++; return c; } @@ -89,7 +70,7 @@ namespace odb if (max_ == 0 || in_use_ < max_) { shared_ptr c (create ()); - c->pool_ = this; + c->callback_ = &c->cb_; in_use_++; return c; } @@ -105,7 +86,12 @@ namespace odb void connection_pool_factory:: database (database_type& db) { - db_ = &db; + bool first (db_ == 0); + + connection_factory::database (db); + + if (!first) + return; if (min_ > 0) { @@ -119,7 +105,7 @@ namespace odb bool connection_pool_factory:: release (pooled_connection* c) { - c->pool_ = 0; + c->callback_ = 0; lock l (mutex_); @@ -149,28 +135,26 @@ namespace odb // connection_pool_factory::pooled_connection:: - pooled_connection (database_type& db) - : connection (db), pool_ (0) + pooled_connection (connection_pool_factory& f) + : connection (f) { - 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, PGconn* handle) - : connection (db, handle), pool_ (0) + pooled_connection (connection_pool_factory& f, PGconn* 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/pgsql/connection-factory.hxx b/odb/pgsql/connection-factory.hxx index a0009ff..0ee2197 100644 --- a/odb/pgsql/connection-factory.hxx +++ b/odb/pgsql/connection-factory.hxx @@ -25,42 +25,17 @@ namespace odb { namespace pgsql { - class LIBODB_PGSQL_EXPORT connection_factory - { - public: - virtual connection_ptr - connect () = 0; - - public: - typedef pgsql::database database_type; - - virtual void - database (database_type&) = 0; - - virtual - ~connection_factory (); - }; - class LIBODB_PGSQL_EXPORT new_connection_factory: public connection_factory { public: - new_connection_factory () - : db_ (0) - { - } + new_connection_factory () {} virtual connection_ptr connect (); - virtual void - database (database_type&); - private: new_connection_factory (const new_connection_factory&); new_connection_factory& operator= (const new_connection_factory&); - - private: - database_type* db_; }; class LIBODB_PGSQL_EXPORT connection_pool_factory: @@ -86,7 +61,6 @@ namespace odb min_ (min_connections), in_use_ (0), waiters_ (0), - db_ (0), cond_ (mutex_) { // max_connections == 0 means unlimited. @@ -111,8 +85,8 @@ namespace odb class LIBODB_PGSQL_EXPORT pooled_connection: public connection { public: - pooled_connection (database_type&); - pooled_connection (database_type&, PGconn*); + pooled_connection (connection_pool_factory&); + pooled_connection (connection_pool_factory&, PGconn*); private: static bool @@ -121,11 +95,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; @@ -152,7 +122,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/pgsql/connection.cxx b/odb/pgsql/connection.cxx index a39f6a8..dcc841b 100644 --- a/odb/pgsql/connection.cxx +++ b/odb/pgsql/connection.cxx @@ -28,9 +28,10 @@ namespace odb namespace pgsql { connection:: - connection (database_type& db) - : odb::connection (db), db_ (db), failed_ (false) + connection (connection_factory& cf) + : odb::connection (cf), failed_ (false) { + database_type& db (database ()); handle_.reset (PQconnectdb (db.conninfo ().c_str ())); if (handle_ == 0) @@ -42,8 +43,8 @@ namespace odb } connection:: - connection (database_type& db, PGconn* handle) - : odb::connection (db), db_ (db), handle_ (handle), failed_ (false) + connection (connection_factory& cf, PGconn* handle) + : odb::connection (cf), handle_ (handle), failed_ (false) { init (); } @@ -117,5 +118,19 @@ namespace odb return count; } + + // connection_factory + // + connection_factory:: + ~connection_factory () + { + } + + void connection_factory:: + database (database_type& db) + { + odb::connection_factory::db_ = &db; + db_ = &db; + } } } diff --git a/odb/pgsql/connection.hxx b/odb/pgsql/connection.hxx index 78d8cd5..0f1d78c 100644 --- a/odb/pgsql/connection.hxx +++ b/odb/pgsql/connection.hxx @@ -27,6 +27,7 @@ namespace odb namespace pgsql { class statement_cache; + class connection_factory; class connection; typedef details::shared_ptr connection_ptr; @@ -40,14 +41,11 @@ namespace odb virtual ~connection (); - connection (database_type&); - connection (database_type&, PGconn* handle); + connection (connection_factory&); + connection (connection_factory&, PGconn* handle); database_type& - database () - { - return db_; - } + database (); public: virtual transaction_impl* @@ -135,11 +133,6 @@ namespace odb friend class transaction_impl; // invalidate_results() private: - // Needed to break the circular connection-database dependency - // (odb::connection has the odb::database member). - // - database_type& db_; - auto_handle handle_; bool failed_; @@ -148,6 +141,33 @@ namespace odb // details::unique_ptr statement_cache_; }; + + class LIBODB_PGSQL_EXPORT connection_factory: + public odb::connection_factory + { + public: + typedef pgsql::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/pgsql/connection.ixx b/odb/pgsql/connection.ixx index f549dd4..92ce453 100644 --- a/odb/pgsql/connection.ixx +++ b/odb/pgsql/connection.ixx @@ -6,6 +6,12 @@ namespace odb { namespace pgsql { + 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/pgsql/database.hxx b/odb/pgsql/database.hxx index 6ad1ba9..bf77397 100644 --- a/odb/pgsql/database.hxx +++ b/odb/pgsql/database.hxx @@ -12,6 +12,7 @@ #include // std::ostream #include +#include // ODB_CXX11 #include #include @@ -78,6 +79,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&); @@ -470,6 +477,8 @@ namespace odb } private: + // Note: remember to update move ctor if adding any new members. + // std::string user_; std::string password_; std::string db_; diff --git a/odb/pgsql/database.ixx b/odb/pgsql/database.ixx index ab65be0..591a090 100644 --- a/odb/pgsql/database.ixx +++ b/odb/pgsql/database.ixx @@ -2,12 +2,32 @@ // copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file +#include // move() + #include namespace odb { namespace pgsql { +#ifdef ODB_CXX11 + inline database:: + database (database&& db) // Has to be inline. + : odb::database (std::move (db)), + user_ (std::move (db.user_)), + password_ (std::move (db.password_)), + db_ (std::move (db.db_)), + host_ (std::move (db.host_)), + port_ (db.port_), + socket_ext_ (std::move (db.socket_ext_)), + extra_conninfo_ (std::move (db.extra_conninfo_)), + conninfo_ (std::move (db.conninfo_)), + factory_ (std::move (db.factory_)) + { + factory_->database (*this); // New database instance. + } +#endif + inline connection_ptr database:: connection () { -- cgit v1.1