
Stefan Strasser-2 wrote:
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)?
Because other transaction on another thread has committed an update on res2 between (1) and (2). Depending on the Validation policy the STM system will either invalidate every transaction that can not succeed (setting its stae to rollback only), or do nothing. When validation is used , the victim transaction will see that it is a victim when try to use this resource res2 and then abort itself. Stefan Strasser-2 wrote:
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?
STM check for conflicts in any access. So it is able to see a conflict in (1). Stefan Strasser-2 wrote:
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.
I don't think polling will be satisfactory Stefan Strasser-2 wrote:
what exactly triggers that in Boost.STM at the moment?
STM check also for rollback only state in any access or nested transaction creation. This rollback only state can be set by other transaction as explained above. Stefan Strasser-2 wrote:
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 understand the intent of lazy constructing the local transactions. IMO this lazy construction can be done, but as soon as a resource has already a transaction, any global nested transaction should create a local transaction on it. All the resources have the same nested level of transaction except those that have none. This should solve the preceding issue, and let STM check for rollback only as soon as possible. Stefan Strasser-2 wrote:
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.
It is extrange also tome. Well, I don' use the mixin idiom tis way. For the mutex a double locking patter solve the issue of locking at each call to active(). I will do as follows: struct txmgr : basic_transaction_manager<txmgr,...> { txmgr &instance(){ static txmgr* instance_; static mutex mtx_; if (instance_==0) { scoped_lock<mutex> lk(mtx_); if (instance_==0) instance_ = new txmgr(...); } // here instance_!= 0 return *instance_; } static char *db_filename; ... }; char * txmgr::db_filename="file.db"; int main(){ basic_transaction<txmgr> tx; ... tx.commit(); } Can you found this code on your book? ;-) Best, Vicente -- View this message in context: http://old.nabble.com/-transaction--New-Boost.Transaction-library-under-disc... Sent from the Boost - Dev mailing list archive at Nabble.com.