diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2011-08-24 13:42:04 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2011-08-24 13:42:04 +0200 |
commit | f5d79a0cd5dc12a430d17bbdca7ec5aacb45996c (patch) | |
tree | 10518f3819b50b78470d3612a36a14580ca1ad11 | |
parent | 27e362857cf748a54c62b157113cd4abf7eff570 (diff) |
Add support for transaction multiplexing
Also delay getting a connection until after we do all the sanity
checks (e.g., that there is no active transaction). Otherwise we
are running risk of getting blocked rather than throwing an
exception.
-rw-r--r-- | odb/database.hxx | 4 | ||||
-rw-r--r-- | odb/database.ixx | 6 | ||||
-rw-r--r-- | odb/transaction.cxx | 41 | ||||
-rw-r--r-- | odb/transaction.hxx | 48 |
4 files changed, 71 insertions, 28 deletions
diff --git a/odb/database.hxx b/odb/database.hxx index 2e6c79d..5ec98a7 100644 --- a/odb/database.hxx +++ b/odb/database.hxx @@ -177,8 +177,8 @@ namespace odb // Transactions. // public: - transaction_impl* - begin (); + virtual transaction_impl* + begin () = 0; // Connections. // diff --git a/odb/database.ixx b/odb/database.ixx index ccbbe41..dbdcaec 100644 --- a/odb/database.ixx +++ b/odb/database.ixx @@ -12,12 +12,6 @@ namespace odb { } - inline transaction_impl* database:: - begin () - { - return connection ()->begin (); - } - inline connection_ptr database:: connection () { diff --git a/odb/transaction.cxx b/odb/transaction.cxx index e1fed91..70abd0c 100644 --- a/odb/transaction.cxx +++ b/odb/transaction.cxx @@ -19,10 +19,16 @@ namespace odb static ODB_TLS_POINTER (transaction) current_transaction; transaction:: - transaction (transaction_impl* impl) + transaction (transaction_impl* impl, bool make_current) : finalized_ (false), impl_ (impl) { - tls_set (current_transaction, this); + if (make_current && tls_get (current_transaction) != 0) + throw already_in_transaction (); + + impl_->start (); + + if (make_current) + tls_set (current_transaction, this); } transaction:: @@ -60,14 +66,32 @@ namespace odb } void transaction:: + current (transaction& t) + { + tls_set (current_transaction, &t); + } + + void transaction:: + reset_current () + { + transaction* t (0); + tls_set (current_transaction, t); + } + + void transaction:: commit () { if (finalized_) throw transaction_already_finalized (); finalized_ = true; - transaction* t (0); - tls_set (current_transaction, t); + + if (tls_get (current_transaction) == this) + { + transaction* t (0); + tls_set (current_transaction, t); + } + impl_->commit (); } @@ -78,8 +102,13 @@ namespace odb throw transaction_already_finalized (); finalized_ = true; - transaction* t (0); - tls_set (current_transaction, t); + + if (tls_get (current_transaction) == this) + { + transaction* t (0); + tls_set (current_transaction, t); + } + impl_->rollback (); } diff --git a/odb/transaction.hxx b/odb/transaction.hxx index c2b1f77..0d4f518 100644 --- a/odb/transaction.hxx +++ b/odb/transaction.hxx @@ -22,8 +22,11 @@ namespace odb typedef odb::database database_type; typedef odb::connection connection_type; + // If the second argument is false, then this transaction is not + // made the current transaction of the thread. + // explicit - transaction (transaction_impl*); + transaction (transaction_impl*, bool make_current = true); // Unless the transaction has already been finalized (explicitly // committed or rolled back), the destructor will roll it back. @@ -46,16 +49,26 @@ namespace odb connection_type& connection (); + // Return true if there is a transaction in effect. + // + static bool + has_current (); + // Return current transaction or throw if there is no transaction // in effect. // static transaction& current (); - // Return true if there is a transaction in effect. + // Set the current thread's transaction. // - static bool - has_current (); + static void + current (transaction&); + + // Revert to the no transaction in effect state for the current thread. + // + static void + reset_current (); public: transaction_impl& @@ -74,21 +87,17 @@ namespace odb class LIBODB_EXPORT transaction_impl { - protected: - friend class transaction; - + public: typedef odb::database database_type; typedef odb::connection connection_type; - transaction_impl (database_type& db, connection_type& c) - : database_ (db), connection_ (c) - { - } - virtual ~transaction_impl (); virtual void + start () = 0; + + virtual void commit () = 0; virtual void @@ -103,12 +112,23 @@ namespace odb connection_type& connection () { - return connection_; + return *connection_; + } + + protected: + transaction_impl (database_type& db) + : database_ (db), connection_ (0) + { + } + + transaction_impl (database_type& db, connection_type& c) + : database_ (db), connection_ (&c) + { } protected: database_type& database_; - connection_type& connection_; + connection_type* connection_; }; } |