我有以下锁和线程保护实现:
class Spinlock
{
public:
/* Default constructor/destructor + deleted copy/moving */
void Lock()
{
while (m_flag.test_and_set(std::memory_order_acquire))
{
// spin...
};
}
void Unlock()
{
m_flag.clear(std::memory_order_release);
}
private:
std::atomic_flag m_flag = ATOMIC_FLAG_INIT;
};
template<class ThreadLock>
class ThreadGuard
{
public:
/* Default constructor + deleted copy/moving */
/* Constructor */
ThreadGuard(ThreadLock& lock)
: m_pLock(&lock)
{
m_pLock->Lock();
}
/* Destructor */
~ThreadGuard()
{
m_pLock->Unlock();
}
private:
ThreadLock* m_pLock;
};
现在,让我说我有以下代码:
void LockDataAndSetX()
{
ThreadGuard lock(m_spinLock);
/* ... operations on data here ...*/
}
{
/* code... */
LockDataAndSetX();
/* more code... */
}
我徘徊,如果编译器想要内联LockDataAndSetX函数,它会转换为下面的代码吗?
{
/* code... */
ThreadGuard lock(m_spinLock);
/* ... operations on data here ...*/
/* more code... */
}
我问,因为这对我来说会有问题,因为锁定范围将取决于编译器内联/非内联锁定功能。在这种情况下,我需要删除我的线程保护类。
答案 0 :(得分:2)
变量的范围/生命周期不依赖于内联。内联是一个优化问题,代码必须独立于编译器是否应用内联而具有相同的效果。
您可以想象内联的效果更像如下:
{
/* code... */
{
ThreadGuard lock(m_spinLock);
/* ... operations on data here ...*/
}
/* more code... */
}
另请注意,ThreadGuard
是一个模板,并且类的模板参数推导(基于构造函数参数)适用于C ++ 17。