aboutsummaryrefslogtreecommitdiff
path: root/odb
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-08-24 13:42:04 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-08-24 13:42:04 +0200
commitf5d79a0cd5dc12a430d17bbdca7ec5aacb45996c (patch)
tree10518f3819b50b78470d3612a36a14580ca1ad11 /odb
parent27e362857cf748a54c62b157113cd4abf7eff570 (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.
Diffstat (limited to 'odb')
-rw-r--r--odb/database.hxx4
-rw-r--r--odb/database.ixx6
-rw-r--r--odb/transaction.cxx41
-rw-r--r--odb/transaction.hxx48
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_;
};
}