2013-04-09 113 views
4

我有這樣的方式來實現一個多線程的C++類:重構多線程類爲單線程+多線程

class MyClass{ 
protected: 
    somemutex mutex; 
    void _unsafeMethod(){...}; 
public: 
    void safeMethod{ 
    locker lock(mutex); 
    _unsafeMethod(); 
    } 
} 

我很高興的是,但注意到,在大多數情況下,在多線程支持ISN沒有必要,所以我很樂意把它分成兩類:一個是線程安全的,一個是不安全的,但是表現更好。

問題是,有成千上萬行代碼使用該類,所以我需要保持界面相同。當然,根據是否需要支持MT,類名將在其定義中發生變化。

我腦子裏想的東西像下面這樣:

解決方案A

class MyClass{ 
protected: 
    void _unsafeMethod(){...}; 
public: 
    virtual void safeMethod{ 
    _unsafeMethod() 
    }; 
}; 
class MyThreadSafeClass: public MyClass{ 
protected: 
    somemutex mutex; 
public: 
    virtual void safeMethod{ 
    locker lock(mutex); 
    _unsafeMethod(); 
    }; 
} 

這裏的問題是虛函數調用:它使執行速度較慢,所以我立即失去的利益單線程類的性能提升?從第一次測試,它看起來像

溶液B

class MyClass{ 
protected: 
    somemutex * pmutex; 
    void _unsafeMethod(){...}; 
public: 
    MyClass(bool isthreadsafe){ 
    if(isthreadsafe) 
     pmutex = new somemutex(); 
    else 
     pmutex = NULL; 
    }; 
    void safeMethod{ 
    if(pmutex) 
    { 
     locker lock(*pmutex); 
     _unsafeMethod(); 
    } 
    else 
     _unsafeMethod(); 
    }; 
} 

這第二個解決方案看起來髒兮兮的,總有一個「如果」在每次調用來解決。

您認爲哪種解決方案更高效?你有沒有更好的/更清潔/更有效的解決方案?

非常感謝!

+0

爲什麼不將互斥量作爲參數傳遞給構造函數?這樣你可以選擇任意數量的鎖定機制。 – 2013-04-09 13:56:51

回答

2

您可以使用裝飾模式或包裝。 。

]一種改性包裝內,以便你與虛函數脫身:

class MyClass{ 
protected: 
    void _unsafeMethod(){}; 

}; 

class MyThreadSafeClass{ 
protected: 
    somemutex mutex; 
    MyClass& myclassRef; 
public: 
    MyThreadSafeClass(MyClass& myclass):myclassRef(myclass){} 
    void safeMethod(){ 
    locker lock(mutex); 
    myclassRef._unsafeMethod(); 
    } 
}; 

類調​​用:

MyClass myclass; 
MyThreadSafeClass mythreadsafeclass(myclass); 
mythreadsafeclass.safeMethod(); 

]與虛擬接口裝飾器:

class MyClassInterface{ 
public: 
    virtual void Method()=0; 

}; 

class MyClass : public MyClassInterface{ 
protected: 
    virtual void Method() override{}; 

}; 

class MyThreadSafeClass: public MyClassInterface{ 
protected: 
    somemutex mutex; 
    MyClassInterface& myclassRef; 
public: 
    MyThreadSafeClass(MyClassInterface& myclass):myclassRef(myclass){} 
    virtual void Method() override{ 
    locker lock(mutex); 
    myclassRef.Method(); 
    } 
}; 
+0

虛擬功能在哪裏? o.o – 2013-04-09 14:07:50

+0

不需要。客戶端在處理多線程時只會使用'MyThreadSafeClass'裝飾類。如果'MyClass'被單線程使用,'_unsafeMethod'可以公開。 – 2013-04-09 14:09:44

+0

O.P擔心執行速度,虛擬化可能會讓一些事情變慢一點,但不是太多。 – 2013-04-09 14:12:07

1

您可以將互斥量作爲參數傳遞給構造函數。這將允許您選擇鎖定機制,而不必修改或複製您希望爲每個鎖定類型實施。

class Mutex 
{ 
public: 
    virtual void Lock() = 0; 
}; 

class MyClass 
{ 
protected: 
    Mutex& mutex; 

public: 

    MyClass(Mutex& m) : mutex(m) {} 

    void Lock() 
    { 
     mutex.Lock(); 
    } 
}; 
3

一個直截了當的回答將是一個互斥體類型模板MyClass

template <typename MutexType> 
class MyClass{ 
protected: 
    MutextType mutex; 
public: 
    void safeMethod{ 
    locker lock(mutex); 
    // stuff 
    } 
} 

然後您可以用真實的互斥體或無操作互斥體,以得到你想要的行爲實例化。

+1

+1非常好!!! – 2013-04-10 08:16:53

+0

偉大的方法,我沒有想到,只是不可行因爲我的課是巨大的,並不能在一個.h – FrizzTheSnail 2013-04-10 13:34:33