From 34087db5762e86dcc60e596c70522303a623051c 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/mysql/connection-factory.cxx | 56 ++++++++++++++-------------------------- odb/mysql/connection-factory.hxx | 39 +++------------------------- odb/mysql/connection.cxx | 32 ++++++++++++++++------- odb/mysql/connection.hxx | 42 ++++++++++++++++++++++-------- odb/mysql/connection.ixx | 6 +++++ odb/mysql/database.hxx | 9 +++++++ odb/mysql/database.ixx | 22 ++++++++++++++++ 7 files changed, 114 insertions(+), 92 deletions(-) (limited to 'odb') diff --git a/odb/mysql/connection-factory.cxx b/odb/mysql/connection-factory.cxx index 22278c1..04f7ab5 100644 --- a/odb/mysql/connection-factory.cxx +++ b/odb/mysql/connection-factory.cxx @@ -128,41 +128,22 @@ namespace odb static mysql_process_init mysql_process_init_; } - // - // connection_factory - // - - connection_factory:: - ~connection_factory () - { - } - - // // new_connection_factory // - connection_ptr new_connection_factory:: connect () { tls_get (mysql_thread_init_); - 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:: @@ -205,7 +186,7 @@ namespace odb c = connections_.back (); connections_.pop_back (); - c->pool_ = this; + c->callback_ = &c->cb_; in_use_++; break; } @@ -218,7 +199,7 @@ namespace odb // can return immediately. // c = create (); - c->pool_ = this; + c->callback_ = &c->cb_; in_use_++; return c; } @@ -244,7 +225,12 @@ namespace odb { tls_get (mysql_thread_init_); - db_ = &db; + bool first (db_ == 0); + + connection_factory::database (db); + + if (!first) + return; if (min_ > 0) { @@ -259,7 +245,7 @@ namespace odb release (pooled_connection* c) { c->clear (); - c->pool_ = 0; + c->callback_ = 0; lock l (mutex_); @@ -289,28 +275,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, MYSQL* handle) - : connection (db, handle), pool_ (0) + pooled_connection (connection_pool_factory& f, MYSQL* 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/mysql/connection-factory.hxx b/odb/mysql/connection-factory.hxx index b74708e..bc88570 100644 --- a/odb/mysql/connection-factory.hxx +++ b/odb/mysql/connection-factory.hxx @@ -25,42 +25,17 @@ namespace odb { namespace mysql { - class LIBODB_MYSQL_EXPORT connection_factory - { - public: - virtual connection_ptr - connect () = 0; - - public: - typedef mysql::database database_type; - - virtual void - database (database_type&) = 0; - - virtual - ~connection_factory (); - }; - class LIBODB_MYSQL_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_MYSQL_EXPORT connection_pool_factory: @@ -91,7 +66,6 @@ namespace odb ping_ (ping), in_use_ (0), waiters_ (0), - db_ (0), cond_ (mutex_) { // max_connections == 0 means unlimited. @@ -116,8 +90,8 @@ namespace odb class LIBODB_MYSQL_EXPORT pooled_connection: public connection { public: - pooled_connection (database_type&); - pooled_connection (database_type&, MYSQL*); + pooled_connection (connection_pool_factory&); + pooled_connection (connection_pool_factory&, MYSQL*); private: static bool @@ -126,11 +100,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; @@ -158,7 +128,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/mysql/connection.cxx b/odb/mysql/connection.cxx index 4b57287..11bbc83 100644 --- a/odb/mysql/connection.cxx +++ b/odb/mysql/connection.cxx @@ -20,21 +20,20 @@ namespace odb namespace mysql { connection:: - connection (database_type& db) - : odb::connection (db), - db_ (db), - failed_ (false), - active_ (0) + connection (connection_factory& cf) + : odb::connection (cf), failed_ (false), active_ (0) { if (mysql_init (&mysql_) == 0) throw bad_alloc (); handle_.reset (&mysql_); - if (*db_.charset () != '\0') + database_type& db (database ()); + + if (*db.charset () != '\0') // Can only fail if we pass an unknown option. // - mysql_options (handle_, MYSQL_SET_CHARSET_NAME, db_.charset ()); + mysql_options (handle_, MYSQL_SET_CHARSET_NAME, db.charset ()); // Force the CLIENT_FOUND_ROWS flag so that UPDATE returns the // number of found rows, not the number of changed rows. This @@ -68,9 +67,8 @@ namespace odb } connection:: - connection (database_type& db, MYSQL* handle) - : odb::connection (db), - db_ (db), + connection (connection_factory& cf, MYSQL* handle) + : odb::connection (cf), failed_ (false), handle_ (handle), active_ (0), @@ -203,5 +201,19 @@ namespace odb stmt_handles_.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/mysql/connection.hxx b/odb/mysql/connection.hxx index 2e73473..83d32e5 100644 --- a/odb/mysql/connection.hxx +++ b/odb/mysql/connection.hxx @@ -29,6 +29,7 @@ namespace odb namespace mysql { class statement_cache; + class connection_factory; class connection; typedef details::shared_ptr connection_ptr; @@ -42,14 +43,11 @@ namespace odb virtual ~connection (); - connection (database_type&); - connection (database_type&, MYSQL* handle); + connection (connection_factory&); + connection (connection_factory&, MYSQL* handle); database_type& - database () - { - return db_; - } + database (); public: virtual transaction_impl* @@ -179,11 +177,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_; - bool failed_; MYSQL mysql_; @@ -202,6 +195,33 @@ namespace odb typedef std::vector stmt_handles; stmt_handles stmt_handles_; }; + + class LIBODB_MYSQL_EXPORT connection_factory: + public odb::connection_factory + { + public: + typedef mysql::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/mysql/connection.ixx b/odb/mysql/connection.ixx index 123c952..b439d98 100644 --- a/odb/mysql/connection.ixx +++ b/odb/mysql/connection.ixx @@ -6,6 +6,12 @@ namespace odb { namespace mysql { + 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/mysql/database.hxx b/odb/mysql/database.hxx index 886167d..a0e3bd6 100644 --- a/odb/mysql/database.hxx +++ b/odb/mysql/database.hxx @@ -12,6 +12,7 @@ #include // std::ostream #include +#include // ODB_CXX11 #include #include @@ -116,6 +117,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&); @@ -508,6 +515,8 @@ namespace odb connection_ (); private: + // Note: remember to update move ctor if adding any new members. + // std::string user_; std::string passwd_str_; const char* passwd_; diff --git a/odb/mysql/database.ixx b/odb/mysql/database.ixx index 9e18ff7..5140103 100644 --- a/odb/mysql/database.ixx +++ b/odb/mysql/database.ixx @@ -2,12 +2,34 @@ // copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file +#include // move() + #include namespace odb { namespace mysql { +#ifdef ODB_CXX11 + inline database:: + database (database&& db) // Has to be inline. + : odb::database (std::move (db)), + user_ (std::move (db.user_)), + passwd_str_ (std::move (db.passwd_str_)), + passwd_ (db.passwd_ != 0 ? passwd_str_.c_str () : 0), + db_ (std::move (db.db_)), + host_ (std::move (db.host_)), + port_ (db.port_), + socket_str_ (std::move (db.socket_str_)), + socket_ (db.socket_ != 0 ? socket_str_.c_str () : 0), + charset_ (std::move (db.charset_)), + client_flags_ (db.client_flags_), + factory_ (std::move (db.factory_)) + { + factory_->database (*this); // New database instance. + } +#endif + inline connection_ptr database:: connection () { -- cgit v1.1