c++ - Windows .NET (C++) SpinWait 在 Linux 和 Mac OS X 上的等价物是什么?

标签 c++ linux macos spinwait

Windows .NET (C++) 通过 YIELD/PAUSE 指令为超线程友好的忙等待提供 SpinWait。 Linux 和 Mac OS X 上的等效功能是什么?如果系统调用不可用,如何在用户空间中实现等效项?

参见 Windows Thread::SpinWait

参见 Long Duration Spin-wait Loops on Hyper-Threading Technology Enabled Intel Processors用于讨论自旋等待的性能问题。

最佳答案

参见 https://www.codeproject.com/articles/184046/spin-lock-in-c通过 sameer_87

#include "SpinLock.h"
#include <iostream>

using namespace LockFree;
using namespace std;

void tSpinWait::Lock(tSpinLock &LockObj)
{
    m_iterations = 0;
    while(true)
    {
        // A thread alreading owning the lock shouldn't be allowed to wait to acquire the lock - reentrant safe
        if(LockObj.dest == GetCurrentThreadId())
            break;
        /*
          Spinning in a loop of interlockedxxx calls can reduce the available memory bandwidth and slow
          down the rest of the system. Interlocked calls are expensive in their use of the system memory
          bus. It is better to see if the 'dest' value is what it is expected and then retry interlockedxx.
        */
        if(InterlockedCompareExchange(&LockObj.dest, LockObj.exchange, LockObj.compare) == 0)
        {
            //assign CurrentThreadId to dest to make it re-entrant safe
            LockObj.dest = GetCurrentThreadId();
            // lock acquired 
            break;          
        }

        // spin wait to acquire 
        while(LockObj.dest != LockObj.compare)
        {
            if(HasThreasholdReached())
            {
                if(m_iterations + YIELD_ITERATION >= MAX_SLEEP_ITERATION)
                    Sleep(0);

                if(m_iterations >= YIELD_ITERATION && m_iterations < MAX_SLEEP_ITERATION)
                {
                    m_iterations = 0;
                    SwitchToThread();
                }
            }
            // Yield processor on multi-processor but if on single processor then give other thread the CPU
            m_iterations++;
            if(Helper::GetNumberOfProcessors() > 1) { YieldProcessor(/*no op*/); }
            else { SwitchToThread(); }              
        }               
    }
}
//

void tSpinWait::Unlock(tSpinLock &LockObj)
{
    if(LockObj.dest != GetCurrentThreadId())
        throw std::runtime_error("Unexpected thread-id in release");
    // lock released
    InterlockedCompareExchange(&LockObj.dest, LockObj.compare, GetCurrentThreadId());   
}

关于c++ - Windows .NET (C++) SpinWait 在 Linux 和 Mac OS X 上的等价物是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31245364/

相关文章:

linux - Apache Webserver - 如何写入权限设置为 755 而不是 777 的目录/文件

c++ - 单向链表的实现

c++ - 将 Eigen 数组行保存在变量中

linux - 读取一个文件,一个 block 一个 block

Linux 调度策略 : SCHED_FIFO against SCHED_RR

java - Mac上java安装在哪里。我找不到

php - 我应该使用什么开发记事本?

c++ - "const"函数有什么用?

c++ - 使用 STL 的图形(列表 vector ,即邻接列表)- C++

Objective-C (Mac) try-catch 未捕获异常