godot/thirdparty/embree/common/sys/barrier.cpp

// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#include "barrier.h"
#include "condition.h"
#include "regression.h"
#include "thread.h"

#if defined (__WIN32__)

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

namespace embree
{
  struct BarrierSysImplementation
  {
    __forceinline BarrierSysImplementation (size_t N) 
      : i(0), enterCount(0), exitCount(0), barrierSize(0) 
    {
      events[0] = CreateEvent(nullptr, TRUE, FALSE, nullptr);
      events[1] = CreateEvent(nullptr, TRUE, FALSE, nullptr);
      init(N);
    }
    
    __forceinline ~BarrierSysImplementation ()
    {
      CloseHandle(events[0]);
      CloseHandle(events[1]);
    }
    
    __forceinline void init(size_t N) 
    {
      barrierSize = N;
      enterCount.store(N);
      exitCount.store(N);
    }

    __forceinline void wait()
    {
      /* every thread entering the barrier decrements this count */
      size_t i0 = i;
      size_t cnt0 = enterCount--;

      /* all threads except the last one are wait in the barrier */
      if (cnt0 > 1) 
      {
        if (WaitForSingleObject(events[i0], INFINITE) != WAIT_OBJECT_0)
          THROW_RUNTIME_ERROR("WaitForSingleObjects failed");
      }
      
      /* the last thread starts all threads waiting at the barrier */
      else 
      {
        i = 1-i;
        enterCount.store(barrierSize);
        if (SetEvent(events[i0]) == 0)
          THROW_RUNTIME_ERROR("SetEvent failed");
      }

      /* every thread leaving the barrier decrements this count */
      size_t cnt1 = exitCount--;

      /* the last thread that left the barrier resets the event again */
      if (cnt1 == 1) 
      {
        exitCount.store(barrierSize);
        if (ResetEvent(events[i0]) == 0)
          THROW_RUNTIME_ERROR("ResetEvent failed");
      }
    }

  public:
    HANDLE events[2];
    atomic<size_t> i;
    atomic<size_t> enterCount;
    atomic<size_t> exitCount;
    size_t barrierSize;
  };
}

#else

namespace embree
{
  struct BarrierSysImplementation
  {};
}

#endif

namespace embree
{
  BarrierSys::BarrierSys (size_t N) {}

  BarrierSys::~BarrierSys () {}

  void BarrierSys::init(size_t count) {}

  void BarrierSys::wait() {}

  LinearBarrierActive::LinearBarrierActive (size_t N) 
    :{}

  LinearBarrierActive::~LinearBarrierActive() 
  {}

  void LinearBarrierActive::init(size_t N) 
  {}

  void LinearBarrierActive::wait (const size_t threadIndex)
  {}

  struct barrier_sys_regression_test : public RegressionTest
  {};

  barrier_sys_regression_test barrier_sys_regression_test;
}