Class 与 C++ 中的所有同步方法

Class with all synchronized methods in C++

在Java中我们可以创建一个class

class Test {
    public synchronized void  fn1() {

    }

    public synchronized void  fn2() {

    }

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

在 C++ 中,如果我想模仿功能,一种方法是

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.
}

简而言之,我想做的就是使用 RAII 进行锁定以及允许函数相互调用。在没有 calledFromWithinClass 标志的 C++ 中,如果外部函数已获取锁,则内部函数无法获取锁并且代码会卡住。

如您所见,代码很复杂,请问在 C++ 中有没有其他方法可以做到这一点。

我只能使用 C++98,你可以假设 class 中的所有方法都是同步的(即需要锁)

我可以建议两个选项:

  1. 只需使用 boost::recursive_mutex(或 C++11 中的 std::recursive_mutex)。

  2. (更好)始终从同步代码中调用非同步私有实现:

    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();
        }
    }