Before anything: I'm not a developer and I might not understand some of your messages, and as English is not my native language my question could be hard to understand.
Considering :
class MyVector
{
std::vector<command> vec;
std::mutex vector_m;
public:
void MVpush_back(command t)
{
this->vector_m.lock();
this->vec.push_back(t);
this->vector_m.unlock();
}
};
command
is a custom class (its content doesn't seem relevant here; copy constructor does exist).
Basically, as I have a lot of possible writer & readers, thus I want to force the use of the mutex
to access to the vec
parameter.
As I'll only use push_back()
, erase()
and find()
I could redefine them, but I was wondering if there is a way not have to redefine all functions.
something like:
<template> safe(*function name*<template>)
{
this->vector_m.lock();
<template> retval = vec.*function name*<parameter>;
this->vector_m.unlock();
return retval;
}
where the function to call is a kind of parameter...
I thought it could be done using std::initializer_list<type>
but the type requirement is blocking.
Is there a way to do such a thing?
Rephrased question: is there a way to push a function with parameter(1) as parameter of a function(2) and make function(2) call function(1) ?
If you don't mind sacrificing the use of the member access operator (.
), you can wrap all the vector operations neatly into lockable operations.
class MyVector {
std::vector<command> vec;
std::mutex vector_m;
struct locker {
MyVector& _ref;
locker(MyVector& parent) : _ref(parent) {
_ref.vector_m.lock();
}
~locker() { _ref.vector_m.unlock(); }
std::vector<command>* operator->() && { return &_ref.vec; }
};
public:
locker operator->() { return {*this}; }
};
Now, every access to the underlying vector will lock and unlock the vector for the duration of the operation:
MyVector mv;
mv->push_back(/* ... */);
// This locks the mutex before doing the push back
// And unlocks it immediately after, even in the face of exceptions.
The magic is in operator->
acting in a transitive manner. It is applied to the return value of itself until a regular pointer is returned, which is then accessed as usual. But every temporary along the way is created and destroyed in LIFO order. So the temporary MyVector::locker
object has a lifetime that is just the duration of the access more or less.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With