我认为这可能会对你正在尝试实现的内容有所帮助。现在,我向您展示的模板类是使用Windows平台锁定线程编写的,您可以根据需要修改此类以适用于其他操作系统-平台。它仅用作说明如何实现上述语义的示例。这个类可以在Visual Studio 2015 CE中编译、运行并以0的代码退出。该类依赖于<Windows.h>
头文件,用于使用CRITICAL_SECTION
、EnterCriticalSection()
、LeaveCriticalSection()
、InitializeCriticalSection()
和DeleteCriticalSection()
。如果其他库(如boost库)中有这些的替代方法,则可以轻松编写此类以实现相同的功能。该类旨在在跨多个线程工作时将用户定义的类对象锁定为易失性。
VolatileLocker.h
#ifndef VOLATILE_LOCKER_H
#define VOLATILE_LOCKER_H
#include <Windows.h>
template<typename T>
class VolatileLocker {
private:
T* m_pObject;
CRITICAL_SECTION* m_pCriticalSection;
public:
VolatileLocker( volatile T& objectToLock, CRITICAL_SECTION& criticalSection );
~VolatileLocker();
T* operator->();
private:
VolatileLocker( const VolatileLocker& c );
VolatileLocker& operator=( const VolatileLocker& c );
};
#include "VolatileLocker.inl"
#endif
VolatileLocker.inl
template<typename T>
VolatileLocker<T>::VolatileLocker( volatile T& objectToLock, CRITICAL_SECTION& criticalSection ) :
m_pObject( const_cast<T*>( &objectToLock ) ),
m_pCriticalSection( &criticalSection ) {
EnterCriticalSection( m_pCriticalSection );
}
template<typename T>
VolatileLocker<T>::~VolatileLocker() {
LeaveCriticalSection( m_pCriticalSection );
}
template <typename T>
T* VolatileLocker<T>::operator->() {
return m_pObject;
}
VolatileLocker.cpp
现在这里是主要的运行应用程序,它使用了模板化的易失性锁类和放置新操作符。
#include <iostream>
#include "VolatileLocker.h"
static CRITICAL_SECTION s_criticalSection;
class SomeClass
int getValue() const
};
int main()
输出
2
4
4
注意:
需要注意的是,初始本地堆栈变量本身并不是易失性的。如果您尝试将堆栈变量声明为易失性,并直接使用它:
volatile SomeClass localStackObject( 2 );
SomeClass* pSomeClass = nullptr;
pSomeClass = &localStackObject;
如果你试图通过直接使用易失性局部变量来解决这个问题,你仍然可以将它与VolatileLocker一起使用,但你将无法像这个片段显示的那样使用放置new。
std::cout << VolatileLocker<SomeClass>( localStackObject, s_criticalSection )->getValue() << std::endl; // Line Okay - Notice using object directly and no dereferencing.
// However when we get to this line of code here:
new (localStackObject) SomeClass( 4 ); // Does Not Compile. There Is No Instance Of Operator New To Match The Argument List
// To Fix That We Can Do This:
new ( const_cast<SomeClass*>( &localStackObject) ) SomeClass( 4 ); // This Will Compile
然而,使用这种设计方法访问任何成员时,您必须使用VolatileLocker来访问类的方法,因此不能直接使用localStackObject。
// This Is Invalid:
std::cout << localStackObject.getValue() << std::endl;
// Use This Instead:
std::cout << VolatileLocker<SomeClass>( localStackObject, s_criticalSection )->getValue() << std::endl;
作为一个重要的提示,请注意这个类最初是针对具体的Windows平台设计的,然而,只需将CRITICAL_SECTION替换为任何可用的跨平台等效函数,就可以轻松地以跨平台模块化的方式编写此模板类的概念。
以下是在Linux/Unix系统上工作的参考答案:
stackoverflow/multithreading/linux
以下是在Mac/Apple系统上工作的参考答案:
stackoverflow/multithreading/mac
以下是编写跨平台模块化等效项的参考资料:
- cppreference/thread
- cppreference/condition_variable
volatile
很重要。 - M.M