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