Opened 8 years ago
Closed 8 years ago
#10128 closed Feature Requests (wontfix)
Use lockable_adapter with const objects or const members
Reported by: | anonymous | Owned by: | viboes |
---|---|---|---|
Milestone: | Component: | thread | |
Version: | Boost 1.54.0 | Severity: | Problem |
Keywords: | Cc: |
Description (last modified by )
I would like to use lockable_adapter pattern with const objects. Usually, we need to access in protected mode to one const object (read some value).
We have a compiler error when we connect unique_lock and one derived class from lockable_adapter and the object is const.
int func(const Class1& obj) { boost::unique_lock<Class1> lock(obj); //boost::unique_lock<Class1> lock(const_cast<Class1&>(obj)); return obj.get(); }
->
error C2664: 'boost::unique_lock<Mutex>::unique_lock(boost::upgrade_lock<Mutex> &)' : no se puede convertir el parámetro 1 de 'const Class1' a 'boost::upgrade_lock<Mutex> &'
The solution for us is rewrite the sentence with one const_cast<Class1> -> boost::unique_lock<Class1> lock(const_cast<Class1&>(obj));
We are using Visual C++ 2010
Best regards
Attachments (1)
Change History (16)
by , 8 years ago
Attachment: | example_lock_constObject.cpp added |
---|
comment:1 by , 8 years ago
Description: | modified (diff) |
---|---|
Owner: | changed from | to
Status: | new → assigned |
comment:2 by , 8 years ago
The error I'm seen is
test_10128.cpp: In function ‘int func(const Class1&)’: test_10128.cpp:29:40: erreur: no matching function for call to ‘boost::unique_lock<Class1>::unique_lock(const Class1&)’ boost::unique_lock<Class1> lock(obj);
A unique_lock<Class1> doesn't accepts a const& Class1 reference.
You wold need to use
boost::unique_lock<const Class1> lock(obj);
And this patch
--- a/include/boost/thread/lockable_adapter.hpp +++ b/include/boost/thread/lockable_adapter.hpp @@ -37,11 +37,11 @@ namespace boost basic_lockable_adapter() {} - void lock() + void lock() const { lockable().lock(); } - void unlock() + void unlock() const { lockable().unlock(); }
Please, could you tell me if this work for you?
comment:3 by , 8 years ago
For me this patch is enough. It's working properly in visual C++ 2010. I suppose, it will be necesary this modification in *_lockable_adapter as timed_lockable_adapter, shared_lockable_adapter, upgrade_lockable_adapter...
Thank you very much.
comment:4 by , 8 years ago
After more thoughts, I have some doubts. I'm not sure it is correct to make these lock/unlock functions const. These functions are public making the nested mutex a salient attribute.
It would be different is the mutex was not salient. E.g. synchronized_value wraps a type and makes the synchronized mutex not salient. Please, could you see if you can use synchronized_value instead?
comment:5 by , 8 years ago
After yet more thoughts, lockable_adapter<const X> could be specialized so that the lock/unlcok operations do nothing (as there is no writter) and are const. What do you think?
comment:6 by , 8 years ago
For me, this last thought is better. Then, I suppose, we can use lockable_adapeter<const X>.
comment:7 by , 8 years ago
There is a little problem as we can not change the inheritance of CLass1 :(
class Class1 : lockable_adapter<Class1> {...};
comment:8 by , 8 years ago
Ok. I can specialize lockable_adapter<Class1> with const members. Are you in agree with me?
comment:10 by , 8 years ago
I could derive lockable_adapter to lockable_adapter2 and use its const members.
template <typename BasicLockable> class basic_lockable_adapter2 : public boost::basic_lockable_adapter<BasicLockable> { public: basic_lockable_adapter2() {} void lock() const { lockable().lock(); } void unlock() const { lockable().unlock(); } }; class Class1 : public basic_lockable_adapter2<boost::recursive_mutex> { public: Class1() :_i(0){} virtual ~Class1(){} void set(int i) { _i = i; } int get() const { return _i; } private: int _i; };
comment:11 by , 8 years ago
This doesn't corresponds to a const specialization of lockable_adapter.
BTW, I'm really thinking about the usefulness of lockable_adapter :( What about
class Class1 : boost::recursive_mutex { ... };
?
comment:12 by , 8 years ago
Then, If I try to change class1 with this code
class Class1 : public boost::recursive_mutex { public: Class1() :_i(0){} virtual ~Class1(){} void set(int i) { _i = i; } int get() const { return _i; } private: int _i; }; int func(const Class1& obj) { boost::unique_lock<const Class1> lock(obj); //boost::unique_lock<Class1> lock(obj); //boost::unique_lock<Class1> lock(const_cast<Class1&>(obj)); return obj.get(); } int _tmain(int argc, _TCHAR* argv[]) { Class1 obj; { boost::unique_lock<Class1> lock(obj); obj.set(1); } func(obj); return 0; }
Visual C++ 2010 says me:
1>c:\desarrollo\externo\boost\boost_1_55_0\boost\thread\lock_types.hpp(331): error C2662: 'boost::detail::basic_recursive_mutex_impl<underlying_mutex_type>::unlock' : no se puede convertir el puntero 'this' de 'const Class1' a 'boost::detail::basic_recursive_mutex_impl<underlying_mutex_type> &' 1> with 1> [ 1> underlying_mutex_type=boost::detail::basic_timed_mutex 1> ] 1> Se pierden calificadores en la conversión 1> c:\desarrollo\externo\boost\boost_1_55_0\boost\thread\lock_types.hpp(328) : durante la compilación de la función miembro de plantilla de clase 'boost::unique_lock<Mutex>::~unique_lock(void)' 1> with 1> [ 1> Mutex=const Class1 1> ] 1> c:\temp\example_lock_constobject\example_lock_constobject.cpp(50) : vea la referencia a la creación de instancias de plantilla de clase 'boost::unique_lock<Mutex>' que se está compilando 1> with 1> [ 1> Mutex=const Class1 1> ]
comment:13 by , 8 years ago
Off course :(
I don't see how the code in comment 10 would compile after having a specialization for const X.
comment:14 by , 8 years ago
Then, I'm afraid, I will use a member mutex in Class1 with "boost::unique_lock<boost::recursive_mutex> sl(m_mt)"
Thank you very much for your time.
comment:15 by , 8 years ago
Milestone: | To Be Determined |
---|---|
Resolution: | → wontfix |
Status: | assigned → closed |
Error example