From 476f21938f75553d6bff5e8780b537f7182c5675 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/oracle/auto-handle.hxx | 20 ++++++++++++++ odb/oracle/connection-factory.cxx | 56 ++++++++++++++------------------------- odb/oracle/connection-factory.hxx | 39 +++------------------------ odb/oracle/connection.cxx | 48 ++++++++++++++++++++++----------- odb/oracle/connection.hxx | 39 +++++++++++++++++++++------ odb/oracle/connection.ixx | 6 +++++ odb/oracle/database.hxx | 9 +++++++ odb/oracle/database.ixx | 22 +++++++++++++++ 8 files changed, 144 insertions(+), 95 deletions(-) diff --git a/odb/oracle/auto-handle.hxx b/odb/oracle/auto-handle.hxx index cdbda4f..f764fe2 100644 --- a/odb/oracle/auto-handle.hxx +++ b/odb/oracle/auto-handle.hxx @@ -7,6 +7,8 @@ #include +#include // ODB_CXX11 + #include #include @@ -125,6 +127,16 @@ namespace odb h_ = h; } +#ifdef ODB_CXX11 + auto_handle (auto_handle&& ah): h_ (ah.release ()) {} + auto_handle& operator= (auto_handle&& ah) + { + if (this != &ah) + reset (ah.release ()); + return *this; + } +#endif + private: auto_handle (const auto_handle&); auto_handle& operator= (const auto_handle&); @@ -198,6 +210,10 @@ namespace odb } private: + auto_handle (const auto_handle&); + auto_handle& operator= (const auto_handle&); + + private: OCISvcCtx* h_; OCIError* e_; }; @@ -259,6 +275,10 @@ namespace odb } private: + auto_handle (const auto_handle&); + auto_handle& operator= (const auto_handle&); + + private: OCIStmt* h_; ub4 release_mode_; OCIError* e_; diff --git a/odb/oracle/connection-factory.cxx b/odb/oracle/connection-factory.cxx index 4658a22..17bb68f 100644 --- a/odb/oracle/connection-factory.cxx +++ b/odb/oracle/connection-factory.cxx @@ -15,39 +15,20 @@ namespace odb namespace oracle { - // - // 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, OCISvcCtx* handle) - : connection (db, handle), pool_ (0) + pooled_connection (connection_pool_factory& f, OCISvcCtx* 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/oracle/connection-factory.hxx b/odb/oracle/connection-factory.hxx index aa8ed5b..67d18b1 100644 --- a/odb/oracle/connection-factory.hxx +++ b/odb/oracle/connection-factory.hxx @@ -25,42 +25,17 @@ namespace odb { namespace oracle { - class LIBODB_ORACLE_EXPORT connection_factory - { - public: - virtual connection_ptr - connect () = 0; - - public: - typedef oracle::database database_type; - - virtual void - database (database_type&) = 0; - - virtual - ~connection_factory (); - }; - class LIBODB_ORACLE_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_ORACLE_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_ORACLE_EXPORT pooled_connection: public connection { public: - pooled_connection (database_type&); - pooled_connection (database_type&, OCISvcCtx*); + pooled_connection (connection_pool_factory&); + pooled_connection (connection_pool_factory&, OCISvcCtx*); 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/oracle/connection.cxx b/odb/oracle/connection.cxx index bb06121..79f35c0 100644 --- a/odb/oracle/connection.cxx +++ b/odb/oracle/connection.cxx @@ -22,18 +22,19 @@ namespace odb namespace oracle { connection:: - connection (database_type& db) - : odb::connection (db), - db_ (db), + connection (connection_factory& cf) + : odb::connection (cf), failed_ (false), statement_cache_ (new statement_cache_type (*this)), lob_buffer_ (0) { sword r (0); + database_type& db (database ()); + { OCIError* e (0); - r = OCIHandleAlloc (db_.environment (), + r = OCIHandleAlloc (db.environment (), reinterpret_cast (&e), OCI_HTYPE_ERROR, 0, @@ -48,7 +49,7 @@ namespace odb auto_handle auth_info; { OCIAuthInfo* a (0); - r = OCIHandleAlloc (db_.environment (), + r = OCIHandleAlloc (db.environment (), reinterpret_cast (&a), OCI_HTYPE_AUTHINFO, 0, @@ -63,8 +64,8 @@ namespace odb r = OCIAttrSet ( auth_info, OCI_HTYPE_AUTHINFO, - reinterpret_cast (const_cast (db_.user ().c_str ())), - static_cast (db_.user ().size ()), + reinterpret_cast (const_cast (db.user ().c_str ())), + static_cast (db.user ().size ()), OCI_ATTR_USERNAME, error_); @@ -75,8 +76,8 @@ namespace odb auth_info, OCI_HTYPE_AUTHINFO, reinterpret_cast ( - const_cast (db_.password ().c_str ())), - static_cast (db_.password ().size ()), + const_cast (db.password ().c_str ())), + static_cast (db.password ().size ()), OCI_ATTR_PASSWORD, error_); @@ -87,12 +88,12 @@ namespace odb OCISvcCtx* s (0); r = OCISessionGet ( - db_.environment (), + db.environment (), error_, &s, auth_info, - reinterpret_cast (const_cast (db_.db ().c_str ())), - static_cast (db_.db ().size ()), + reinterpret_cast (const_cast (db.db ().c_str ())), + static_cast (db.db ().size ()), 0, 0, 0, @@ -108,18 +109,19 @@ namespace odb } connection:: - connection (database_type& db, OCISvcCtx* handle) - : odb::connection (db), - db_ (db), + connection (connection_factory& cf, OCISvcCtx* handle) + : odb::connection (cf), failed_ (false), statement_cache_ (new statement_cache_type (*this)), lob_buffer_ (0) { sword r (0); + database_type& db (database ()); + { OCIError* e (0); - r = OCIHandleAlloc (db_.environment (), + r = OCIHandleAlloc (db.environment (), reinterpret_cast (&e), OCI_HTYPE_ERROR, 0, @@ -156,5 +158,19 @@ namespace odb generic_statement st (*this, string (s, n)); return st.execute (); } + + // connection_factory + // + connection_factory:: + ~connection_factory () + { + } + + void connection_factory:: + database (database_type& db) + { + odb::connection_factory::db_ = &db; + db_ = &db; + } } } diff --git a/odb/oracle/connection.hxx b/odb/oracle/connection.hxx index 40a8ddd..e8bcdae 100644 --- a/odb/oracle/connection.hxx +++ b/odb/oracle/connection.hxx @@ -28,6 +28,7 @@ namespace odb namespace oracle { class statement_cache; + class connection_factory; class connection; typedef details::shared_ptr connection_ptr; @@ -41,14 +42,11 @@ namespace odb virtual ~connection (); - connection (database_type&); - connection (database_type&, OCISvcCtx* handle); + connection (connection_factory&); + connection (connection_factory&, OCISvcCtx* handle); database_type& - database () - { - return db_; - } + database (); public: virtual transaction_impl* @@ -144,8 +142,6 @@ namespace odb friend class transaction_impl; // invalidate_results() private: - database_type& db_; - // It is important that the error_ member is declared before the // handle_ member as handle_ depends on error_ during destruction. // @@ -157,6 +153,33 @@ namespace odb details::unique_ptr statement_cache_; details::buffer lob_buffer_; }; + + class LIBODB_ORACLE_EXPORT connection_factory: + public odb::connection_factory + { + public: + typedef oracle::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/oracle/connection.ixx b/odb/oracle/connection.ixx index 40a9eda..165c2df 100644 --- a/odb/oracle/connection.ixx +++ b/odb/oracle/connection.ixx @@ -6,6 +6,12 @@ namespace odb { namespace oracle { + 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/oracle/database.hxx b/odb/oracle/database.hxx index 5534800..d4a0410 100644 --- a/odb/oracle/database.hxx +++ b/odb/oracle/database.hxx @@ -12,6 +12,7 @@ #include // std::ostream #include +#include // ODB_CXX11 #include #include @@ -80,6 +81,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&); @@ -505,6 +512,8 @@ namespace odb connection_ (); private: + // Note: remember to update move ctor if adding any new members. + // std::string user_; std::string password_; diff --git a/odb/oracle/database.ixx b/odb/oracle/database.ixx index 24f435a..167375d 100644 --- a/odb/oracle/database.ixx +++ b/odb/oracle/database.ixx @@ -2,12 +2,34 @@ // copyright : Copyright (c) 2009-2015 Code Synthesis Tools CC // license : ODB NCUEL; see accompanying LICENSE file +#include // move() + #include namespace odb { namespace oracle { +#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_)), + service_ (std::move (db.service_)), + host_ (std::move (db.host_)), + port_ (db.port_), + charset_ (db.charset_), + ncharset_ (db.ncharset_), + auto_environment_ (std::move (db.auto_environment_)), + environment_ (db.environment_), + factory_ (std::move (db.factory_)) + { + factory_->database (*this); // New database instance. + } +#endif + inline connection_ptr database:: connection () { -- cgit v1.1