text: /*
   *
   * Copyright (C) 2019 Intel Corporation
   *
   * SPDX-License-Identifier: MIT
   *
   * @file ze_barrier.cpp
   *
   * @brief C++ wrapper of Intel 'One API' Level-Zero APIs for Barrier
   *
   */
  #include "ze_api.hpp"
  #include "ze_singleton.h"
  
  #define _STRING(s) #s
  #define STRING(s) _STRING(s)
  
  namespace ze
  {
      ///////////////////////////////////////////////////////////////////////////////
      /// @brief Appends an execution and global memory barrier into a command list.
      /// 
      /// @details
      ///     - If numWaitEvents is zero, then all previous commands are completed
      ///       prior to the execution of the barrier.
      ///     - If numWaitEvents is non-zero, then then all phWaitEvents must be
      ///       signaled prior to the execution of the barrier.
      ///     - This command blocks all following commands from beginning until the
      ///       execution of the barrier completes.
      ///     - The application may **not** call this function from simultaneous
      ///       threads with the same command list handle.
      ///     - The implementation of this function should be lock-free.
      /// 
      /// @remarks
      ///   _Analogues_
      ///     - **vkCmdPipelineBarrier**
      ///     - clEnqueueBarrierWithWaitList
      /// 
      /// @throws result_t
      void __zecall
      CommandList::AppendBarrier(
          Event* pSignalEvent,                            ///< [in][optional] pointer to the event to signal on completion
          uint32_t numWaitEvents,                         ///< [in][optional] number of events to wait on before executing barrier
          Event** ppWaitEvents                            ///< [in][optional][range(0, numWaitEvents)] pointer to the events to wait
                                                          ///< on before executing barrier
          )
      {
          thread_local std::vector<ze_event_handle_t> hWaitEvents;
          hWaitEvents.resize( 0 );
          hWaitEvents.reserve( numWaitEvents );
          for( uint32_t i = 0; i < numWaitEvents; ++i )
              hWaitEvents.emplace_back( ( ppWaitEvents ) ? reinterpret_cast<ze_event_handle_t>( ppWaitEvents[ i ]->getHandle() ) : nullptr );
  
          auto result = static_cast<result_t>( ::zeCommandListAppendBarrier(
              reinterpret_cast<ze_command_list_handle_t>( getHandle() ),
              ( pSignalEvent ) ? reinterpret_cast<ze_event_handle_t>( pSignalEvent->getHandle() ) : nullptr,
              numWaitEvents,
              hWaitEvents.data() ) );
  
          if( result_t::SUCCESS != result )
              throw exception_t( result, __FILE__, STRING(__LINE__), "ze::CommandList::AppendBarrier" );
      }
  
      ///////////////////////////////////////////////////////////////////////////////
      /// @brief Appends a global memory ranges barrier into a command list.
      /// 
      /// @details
      ///     - If numWaitEvents is zero, then all previous commands are completed
      ///       prior to the execution of the barrier.
      ///     - If numWaitEvents is non-zero, then then all phWaitEvents must be
      ///       signaled prior to the execution of the barrier.
      ///     - This command blocks all following commands from beginning until the
      ///       execution of the barrier completes.
      ///     - The application may **not** call this function from simultaneous
      ///       threads with the same command list handle.
      ///     - The implementation of this function should be lock-free.
      /// 
      /// @throws result_t
      void __zecall
      CommandList::AppendMemoryRangesBarrier(
          uint32_t numRanges,                             ///< [in] number of memory ranges
          const size_t* pRangeSizes,                      ///< [in][range(0, numRanges)] array of sizes of memory range
          const void** pRanges,                           ///< [in][range(0, numRanges)] array of memory ranges
          Event* pSignalEvent,                            ///< [in][optional] pointer to the event to signal on completion
          uint32_t numWaitEvents,                         ///< [in][optional] number of events to wait on before executing barrier
          Event** ppWaitEvents                            ///< [in][optional][range(0, numWaitEvents)] pointer to the events to wait
                                                          ///< on before executing barrier
          )
      {
          thread_local std::vector<ze_event_handle_t> hWaitEvents;
          hWaitEvents.resize( 0 );
          hWaitEvents.reserve( numWaitEvents );
          for( uint32_t i = 0; i < numWaitEvents; ++i )
              hWaitEvents.emplace_back( ( ppWaitEvents ) ? reinterpret_cast<ze_event_handle_t>( ppWaitEvents[ i ]->getHandle() ) : nullptr );
  
          auto result = static_cast<result_t>( ::zeCommandListAppendMemoryRangesBarrier(
              reinterpret_cast<ze_command_list_handle_t>( getHandle() ),
              numRanges,
              pRangeSizes,
              pRanges,
              ( pSignalEvent ) ? reinterpret_cast<ze_event_handle_t>( pSignalEvent->getHandle() ) : nullptr,
              numWaitEvents,
              hWaitEvents.data() ) );
  
          if( result_t::SUCCESS != result )
              throw exception_t( result, __FILE__, STRING(__LINE__), "ze::CommandList::AppendMemoryRangesBarrier" );
      }
  
      ///////////////////////////////////////////////////////////////////////////////
      /// @brief Ensures in-bound writes to the device are globally observable.
      /// 
      /// @details
      ///     - This is a special-case system level barrier that can be used to ensure
      ///       global observability of writes; typically needed after a producer
      ///       (e.g., NIC) performs direct writes to the device's memory (e.g.,
      ///       Direct RDMA writes).  This is typically required when the memory
      ///       corresponding to the writes is subsequently accessed from a remote
      ///       device.
      ///     - The application may call this function from simultaneous threads.
      ///     - The implementation of this function should be lock-free.
      /// 
      /// @throws result_t
      void __zecall
      Device::SystemBarrier(
          void
          )
      {
          auto result = static_cast<result_t>( ::zeDeviceSystemBarrier(
              reinterpret_cast<ze_device_handle_t>( getHandle() ) ) );
  
          if( result_t::SUCCESS != result )
              throw exception_t( result, __FILE__, STRING(__LINE__), "ze::Device::SystemBarrier" );
      }
  
  } // namespace ze
  
  namespace ze
  {
  } // namespace ze
  