7

In Java we can create a class

class Test {
    public synchronized void  fn1() {

    }

    public synchronized void  fn2() {

    }

    public synchronized void  fn3() {
        fn1(); // Calling another method
    }
}

In C++ if I want to mimic the functionality one way is

class Test {
    private:
        mutex obj;
    public:
       void fn1(bool calledFromWithinClass = false) {
            if(calledFromWithinClass) 
                fn1Helper();
            else
                unique_lock<mutex> lock(obj);
                fn1Helper();
        }

       void fn2(bool calledFromWithinClass = false) {
            if(calledFromWithinClass) 
                fn2Helper();
            else
                unique_lock<mutex> lock(obj);
                fn2Helper();
        }

        void fn3(bool calledFromWithinClass = false) {
            if(calledFromWithinClass) 
                fn3Helper();
            else {
                unique_lock<mutex> lock(obj);
                fn3Helper();
            } 
        }
    private:
        void fn1Helper() {
        }

        void fn2Helper() {
        }

        void fn3Helper() {
             fn1(true);
        }
}
int main() {
    Test obj;
    obj.fn1();
    obj.fn2(); 
    // i.e from outside the class the methods are called with calledFromWithinClass as false.
}

In short all I am trying to do is to use RAII for locking as well as allow functions to call each other. In C++ without the calledFromWithinClass flag if the outer function has acquired the lock the inner function can't acquire the lock and the code gets stuck.

As you can see the code is complicated, is there any other way to do this in C++.

I can only use C++98 and you can assume that all methods in the class are synchronized (i.e need the lock)

user1918858
  • 1,202
  • 1
  • 20
  • 29
  • Possible duplicate of [what is correspoding feature for synchronized in java?](http://stackoverflow.com/questions/5429653/what-is-correspoding-feature-for-synchronized-in-java) – Adam Martin Mar 02 '16 at 02:52
  • I don't recall if `std::recursive_mutex` is in C++98. If so, the mutex can simply be swapped out for a recursive mutex, leaving you with an unconditional mutex acquisition in each method. End of story. – Sam Varshavchik Mar 02 '16 at 02:53
  • 1
    You need some braces around those `else` blocks. – aschepler Mar 02 '16 at 02:55

1 Answers1

8

I can suggest two options:

  1. Just use boost::recursive_mutex instead (or std::recursive_mutex in C++11).

  2. (better) Always call non-synchronized private implementations from your synchronized code:

    class Test {
    private:
        mutex obj;
    public:
       void fn1() {
            unique_lock<mutex> lock(obj);
            fn1Helper();
        }
    
       void fn2(bool calledFromWithinClass = false) {
            unique_lock<mutex> lock(obj);
            fn2Helper();
        }
    
    private:
        void fn1Helper() {
        }
    
        void fn2Helper() {
            fn1Helper();
        }
    }
    
Anton Savin
  • 40,838
  • 8
  • 54
  • 90