
Behalf Of Batov, Vladimir
bool foo(bool threadsafe) { mutex::scoped_lock l(m, !threadsafe); }
I am not sure if the example above is appropriate and indicative of the problem we are trying to solve. Thread-safety should not be a run-time configurable property. Like we do not decide on the fly (at run-time) if our ref.-counting class is to be thread-safe or not. All that is resolved at compile time.
" Thread-safety should not be a run-time configurable property."
I think this is somewhat incorrect as absolutes usually are. I currently have a design where I use both an interface that supports locking and an interface which does not. It is an important feature of the design. Using such a run time parameter is not my choice because I am especially sensitive to performance but it might be a better design for others given other requirements. Non-locking versions are also useful when you want to combine operations. Take a lock, do stuff, and then release lock. Repeatedly locking has deficiencies which may or may not matter to you. $0.005, Matt Hurd. FWIW I wrap boost mutexex and locks in my own policy-like stuff. E.g: ___________________________________________________________ struct shareable { protected: struct adapted_mutex : public boost::rw_mutex { adapted_mutex( lock_priority::type lp = lock_priority::exclusive ) : rw_mutex( convert( lp) ) {} ~adapted_mutex() {} }; struct adapted_try_mutex : public boost::try_rw_mutex { adapted_try_mutex( lock_priority::type lp = lock_priority::exclusive ) : try_rw_mutex( convert( lp) ) {} ~adapted_try_mutex() {} }; struct adapted_timed_mutex : public boost::timed_rw_mutex { adapted_timed_mutex( lock_priority::type lp = lock_priority::exclusive ) : timed_rw_mutex( convert( lp) ) {} ~adapted_timed_mutex() {} }; public: typedef adapted_mutex mutex; typedef adapted_try_mutex try_mutex; typedef adapted_timed_mutex timed_mutex; typedef shareable_lock<mutex> lock; typedef shareable_lock<try_mutex> try_lock; typedef shareable_lock<timed_mutex> timed_lock; typedef atomic_op_interlocked atomic_op; }; ___________________________________________________________ So I can parameterise classes with a synch policy. (Less than ideal but I haven't got around to making it nicer yet.) For the interface where I need to support single threaded and multi-threaded usage of the same object ( as opposed to type ) I use this approach... ___________________________________________________________ template < class S = synch::shareable
class instrument : public synch::monitor<S> { SYNCH_SIMPLE_ATTRIBUTE( susquehanna_code, std::string ); SYNCH_SIMPLE_ATTRIBUTE( exchange_code, std::string ); SYNCH_SIMPLE_ATTRIBUTE( underlying, std::string ); SYNCH_SIMPLE_ATTRIBUTE( bid, double ); SYNCH_SIMPLE_ATTRIBUTE( bid_volume, double ); SYNCH_SIMPLE_ATTRIBUTE( ask, double ); SYNCH_SIMPLE_ATTRIBUTE( ask_volume, double ); SYNCH_SIMPLE_ATTRIBUTE( last, double ); SYNCH_SIMPLE_ATTRIBUTE( last_volume, double ); SYNCH_SIMPLE_ATTRIBUTE( prior_settlement, double ); }; ___________________________________________________________ This way I can use an object in the following manner: ___________________________________________________________ te::instrument<> i_sample; i_sample.exchange_code<true>("hello"); // locking { te::instrument<>::lock lk( i_sample.guard() ); i_sample.exchange_code<false>("hello"); // non-locking } i_sample.exchange_code("hello"); // locking std::string hello = i_sample.exchange_code(); // locking hello = i_sample.exchange_code<false>(); // non-locking hello = i_sample.exchange_code<true>(); // locking hello = i_sample.exchange_code_ref(); // non-locking by nature ___________________________________________________________ I could also specify te::instrument< synch::no_synch > // locking is elided te::instrument< synch::simple > // exclusive locking te::instrument< synch::no_synch > // allows recursive locking te::instrument< synch::shareable > // allows shared or exclusive locks (think r/w) The interface to the non-locking version is still valid. User must code to shareable concept for everything to work for all concepts. Where SYNCH_SIMPLE_ATTRIBUTE defines a bunch of simple attribute helpers and looks like: #define SYNCH_SIMPLE_ATTRIBUTE( VAR_NAME, VAR_TYPE ) \ \ public: \ template< bool > \ void \ VAR_NAME \ ( \ boost::call_traits< VAR_TYPE >::param_type new_ ## VAR_NAME \ ) \ { \ if ( boost::needs_lock<VAR_TYPE>::value ) { \ lock lk(guard_ ); \ VAR_NAME<false>( new_ ## VAR_NAME); \ } else { \ VAR_NAME<false>( new_ ## VAR_NAME); \ } \ } \ \ void \ VAR_NAME \ ( \ boost::call_traits< VAR_TYPE >::param_type new_ ## VAR_NAME \ ) \ { \ VAR_NAME < true > ( new_ ## VAR_NAME ); \ } \ \ template< > \ void \ VAR_NAME<false> \ ( \ boost::call_traits<VAR_TYPE>::param_type new_ ## VAR_NAME \ ) \ { \ VAR_NAME ## _ = new_ ## VAR_NAME; \ } \ \ template< bool > \ VAR_TYPE \ VAR_NAME( ) const \ { \ if ( boost::needs_lock< VAR_TYPE >::value ) { \ lock lk(guard_, synch::lock_status::shared ); \ return VAR_NAME<false>( ); \ } else { \ return VAR_NAME<false>( ); \ } \ } \ \ VAR_TYPE \ VAR_NAME( ) const \ { \ return VAR_NAME<true>( ); \ } \ \ template< > \ VAR_TYPE \ VAR_NAME <false>() const \ { \ return VAR_NAME ## _; \ } \ \ boost::call_traits<VAR_TYPE>::const_reference \ VAR_NAME ## _ref( ) const \ { \ return VAR_NAME ## _; \ } \ \ private: \ VAR_TYPE VAR_NAME ## _; \ SYNCH_SIMPLE_ATTRIBUTE includes an extra thing boost::needs_lock<VAR_TYPE>::value that checks if the size of the type is > pointer size which means, for Intel & AMD, that locking is not required as the assignment of aligned types is atomic. Copy constructors, assignment and cloning are further issues ;-) IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.