
----- Original Message ----- From: <strasser@uni-bremen.de> To: <boost@lists.boost.org> Sent: Sunday, January 17, 2010 10:30 PM Subject: Re: [boost] Boost library submission (poll for interest)
Zitat von "vicente.botet" <vicente.botet@wanadoo.fr>:
Yes. Stefan had suggested this in private e-mails earlier, and I'll have to adapt to fit his interfaces. As I've alluded previously, I would like to see it possible to use Boost.Persistence with my library, as several shortcomings of STLdb would be addressed in that way. Part of doing that involved bringing all transaction control under one manager. Stefans library is the most robust in this sense, so I plan to work with and adapt to his interfaces.
I have proposed in a private mail to split its library in two Boost.Transaction and Boost.Persistency. I think this is the right direction.
before I do that, I would like to have a thorough discussion of the design decisions I made, especially the first one of the list, because it deeply affects the way your libraries would have to be set up.
1.
every transactional entity like a trans_map or a shared_loc must be aware of the static type of the transaction manager, which can change by user configuration.
this results from the following:
every access to a transactional entity without explicit "transaction" argument must go through the transaction manager ==> calls through transaction manager must be efficient ==> there can be no dynamic polymorphism ==> the static type of the transaction manager changes by configuration(a transaction manager using Boost.Persistent has another type than one that uses STLdb, which has another type than a transaction manager using both libraries) ==> all transactional entities must be aware of the static type of the transaction manager.
so in my library every transactional entity is a template with the type of the transaction manager as parameter:
basic_transaction<TxMgr> basic_shared_loc<T,TxMgr> basic_loc_multiset<T,TxMgr,...>
and so on. for convenience of the user that only uses one type of transaction manager, there are aliases defined:
transaction, alias for basic_transaction<transaction_manager>, shared_loc<T>, alias for basic_shared_loc<T,transaction_manager> ...
transaction_manager is a typedef that currently is by default a transaction manager that uses Boost.Persistent, but can be changed by defining BOOST_PERSISTENT_CONFIGURATION before including the aliases.
there are several obstacles with this approach: - every type that ought to be used with a configurable transaction manager must be a template. - C++98 has no template aliases. in C++0x shared_loc could be a simple alias of basic_shared_loc:
template<class T> using shared_loc = basic_loc<T,transaction_manager>;
in C++98 however a class "shared_loc" that acts like an alias for "basic_shared_loc" has to be implemented.
this would have to be done for every class like that of your libraries, too.
I don't think the cost of dynamic polymorphism will be high respect to the cost of a transaction system, and even less if it concerns persistent objects. Anyway, I agree with the static approach. I think that once we will have static polymorphism, it would be very easy to add dynamic polymorphism.
2. do your libraries allow access by multiple threads to the SAME transaction?
Not yet, but I would like to explore how parallelism and transactions can work together.
because this requires a mutex lock in the transaction manager for each access, which might be a performance concern? if your libraries only allow one thread to use a transaction, this mutex lock can be removed by changing a template argument of basic_transaction_manager.
what about having two classes, transaction and shared_transaction? The first one is local to a thread and could be used without the mutext, while the second can be shared between threads and need this mutex protection. We can start by the non-shreable transaction.
3. transactions are bound to the current thread when they are created, but transaction managers are bound to the whole application.
my_transaction_manager t1; my_transaction_manager t2;
//t2 is the current transaction manager, even when another thread is started. bind() can be used to bind another transaction manager for all running threads.
creating and binding of transaction managers is not thread-safe.
Sorry. I'm a little bit lost. Why do you need to change the instance of the transaction manager. I thought that there was only a transaction manager. When an application will need to change it?
4. please have a look at the following parts of the documentation:
https://svn.boost.org/svn/boost/sandbox/persistent/libs/persistent/doc/html/...
TransactionManager concept: https://svn.boost.org/svn/boost/sandbox/persistent/libs/persistent/doc/html/...
ResourceManager concept: https://svn.boost.org/svn/boost/sandbox/persistent/libs/persistent/doc/html/...
I'm not sure if the interface of resource_manager is enough to implement a two-phase commit protocol, but we will see this once we talk about the protocol that ensure that the transaction is ACID for all the resources. I see that there are TransactionManager::transaction and a ResourceManager::transaction types. Could you point on the documentation (if already written) how these types are correlated, and when these function are called? struct TransactionManager { typedef unspecified transaction; ... struct ResourceManager { typedef unspecified services; // A MPL Sequence of tags of all Service concepts implemented by this ResourceManager. typedef unspecified tag; // The tag that identifies this ResourceManager. typedef unspecified transaction; // public member functions unspecified begin_root_transaction() ; unspecified begin_nested_transaction(transaction &) ; void commit_transaction(transaction &) ; void rollback_transaction(transaction &) ; }; Best, Vicente