
Zitat von "vicente.botet" <vicente.botet@wanadoo.fr>:
what conflict can the other resource cause if there is no nested transaction in it?
global_root_tx( resource1_root_tx, resource2_root_tx) ^ ^ | | | | global_nested_tx(resource1_nested_tx, none)
global_nested_tx.commit(): resource1_nested_tx is published into resource1_root_tx. how can this call cause a conflict in resource2?
What I want is the the commit on global_nested_tx see if this transaction must be aborted due the resource2 has conflics with other resources2 of transactions. No need to continue commiting N nesting levels on resorce1 if resource2 has already conflicts. This is maybe an optimization, but we use things like that in Boost.STM.
ok, I see. consider the following example: transaction roottx; //modify res1 //modify res2 (1) { transaction nestedtx; //modify res1 nestedtx.commit(); // (2) } rootrx.commit(); like we´ve said, res2 isn´t taking part in the nested transaction, there is nothing between lines (1) and (2) that could create a conflict in res2. so if Boost.STM tries to discover conflicts as early as possible, why wasn´t the conflict discovered in line (1)? is Boost.STM checking for conflicts regularily, but not on every access, so line (1) doesn´t check for conflicts but you want to check for conflicts if the nestedtx takes, like, 10 seconds of runtime? if that´s the case we could implement something in basic_transaction_manager that regularily calls a resource manager so it can check for conflicts e.g. once every second even if a resource doesn´t take part in a transaction. what exactly triggers that in Boost.STM at the moment? I understand that this must be part of regular calls by the user and cannot be part of another thread, because the exception must be thrown in the user´s thread. but I don´t think that is a reason to drop the lazy construction of resource transactions entirely. take e.g. using Boost.STM and using a remote SQL database together, both managed by Boost.Transaction. starting a transaction to access boost.STM would automatically send a BEGIN to a, possibly remote, SQL database, if resource transaction aren´t lazily constructed, even though all you wanted to do is access some transactional memory.
I don't understand what difference that makes. I thought your point was that the transaction manager should be stored as an invariant singleton. How is that possible, with or without mixin? What does the mixim accomplish? What is the difference between instance() and the current active()?
The trick is that instance is implemented by the Final class, and so can call a specific construtor. Your active() function is implemented by basic_transaction_manager, which is not able to make differences. basic_transaction_manager instance function could in addition ensure that there is a single instance, but doesn't build it.
I think I know what you mean now, but are you really sure you prefer that approach? I see several problems with it, IIUC. example: typedef basic_transaction_manager<my_mixin,...> txmgr; struct my_mixin{ txmgr &instance(){ //construct transaction manager and accompanying resources, //using this->db_filename; } static char *db_filename; ... }; int main(){ my_mixin::db_filename="file.db"; my_mixin::...=...; ... basic_transaction<txmgr> tx; ... tx.commit(); } 1. it´s strange code in my book. requiring the user to initialize runtime configuration options before it is lazily constructed by a call to instance() of basic_transaction. 2. the fact that it is lazily constructed requires the call to instance() be protected by a mutex, or call_once. this is a global mutex, spanning all threads, locked at each call to basic_transaction_manager::active(). did I get that right? if this is not what you meant please provide a code example. Regards, Stefan