2013-04-09 68 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