text: /*
   * Copyright (C) 2019-2020 Intel Corporation
   *
   * SPDX-License-Identifier: MIT
   *
   */
  
  #pragma once
  
  #include "shared/source/utilities/cpuintrinsics.h"
  
  #include "opencl/source/tracing/tracing_handle.h"
  
  #include <atomic>
  #include <thread>
  #include <vector>
  
  namespace HostSideTracing {
  
  #define TRACING_SET_ENABLED_BIT(state) ((state) | (HostSideTracing::TRACING_STATE_ENABLED_BIT))
  #define TRACING_UNSET_ENABLED_BIT(state) ((state) & (~HostSideTracing::TRACING_STATE_ENABLED_BIT))
  #define TRACING_GET_ENABLED_BIT(state) ((state) & (HostSideTracing::TRACING_STATE_ENABLED_BIT))
  
  #define TRACING_SET_LOCKED_BIT(state) ((state) | (HostSideTracing::TRACING_STATE_LOCKED_BIT))
  #define TRACING_UNSET_LOCKED_BIT(state) ((state) & (~HostSideTracing::TRACING_STATE_LOCKED_BIT))
  #define TRACING_GET_LOCKED_BIT(state) ((state) & (HostSideTracing::TRACING_STATE_LOCKED_BIT))
  
  #define TRACING_ZERO_CLIENT_COUNTER(state) ((state) & (HostSideTracing::TRACING_STATE_ENABLED_BIT | HostSideTracing::TRACING_STATE_LOCKED_BIT))
  #define TRACING_GET_CLIENT_COUNTER(state) ((state) & (~(HostSideTracing::TRACING_STATE_ENABLED_BIT | HostSideTracing::TRACING_STATE_LOCKED_BIT)))
  
  #define TRACING_ENTER(name, ...)                                                                  \
      bool isHostSideTracingEnabled_##name = false;                                                 \
      HostSideTracing::name##Tracer tracer_##name;                                                  \
      if (TRACING_GET_ENABLED_BIT(HostSideTracing::tracingState.load(std::memory_order_acquire))) { \
          isHostSideTracingEnabled_##name = HostSideTracing::addTracingClient();                    \
          if (isHostSideTracingEnabled_##name) {                                                    \
              tracer_##name.enter(__VA_ARGS__);                                                     \
          }                                                                                         \
      }
  
  #define TRACING_EXIT(name, ...)                 \
      if (isHostSideTracingEnabled_##name) {      \
          tracer_##name.exit(__VA_ARGS__);        \
          HostSideTracing::removeTracingClient(); \
      }
  
  typedef enum _tracing_notify_state_t {
      TRACING_NOTIFY_STATE_NOTHING_CALLED = 0,
      TRACING_NOTIFY_STATE_ENTER_CALLED = 1,
      TRACING_NOTIFY_STATE_EXIT_CALLED = 2,
  } tracing_notify_state_t;
  
  constexpr size_t TRACING_MAX_HANDLE_COUNT = 16;
  
  constexpr uint32_t TRACING_STATE_ENABLED_BIT = 0x80000000u;
  constexpr uint32_t TRACING_STATE_LOCKED_BIT = 0x40000000u;
  
  extern std::atomic<uint32_t> tracingState;
  extern TracingHandle *tracingHandle[TRACING_MAX_HANDLE_COUNT];
  extern std::atomic<uint32_t> tracingCorrelationId;
  
  bool addTracingClient();
  void removeTracingClient();
  
  class AtomicBackoff {
    public:
      AtomicBackoff() {}
  
      void pause() {
          if (count < loopsBeforeYield) {
              for (uint32_t i = 0; i < count; i++) {
                  NEO::CpuIntrinsics::pause();
              }
              count *= 2;
          } else {
              std::this_thread::yield();
          }
      }
  
    private:
      static const uint32_t loopsBeforeYield = 16;
      uint32_t count = 1;
  };
  
  class clBuildProgramTracer {
    public:
      clBuildProgramTracer() {}
  
      void enter(cl_program *program,
                 cl_uint *numDevices,
                 const cl_device_id **deviceList,
                 const char **options,
                 void(CL_CALLBACK **funcNotify)(cl_program program, void *userData),
                 void **userData) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.program = program;
          params.numDevices = numDevices;
          params.deviceList = deviceList;
          params.options = options;
          params.funcNotify = funcNotify;
          params.userData = userData;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clBuildProgram";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clBuildProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clBuildProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clBuildProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clBuildProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clBuildProgramTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clBuildProgram params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCloneKernelTracer {
    public:
      clCloneKernelTracer() {}
  
      void enter(cl_kernel *sourceKernel,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.sourceKernel = sourceKernel;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCloneKernel";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCloneKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCloneKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_kernel *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCloneKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCloneKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCloneKernelTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCloneKernel params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCompileProgramTracer {
    public:
      clCompileProgramTracer() {}
  
      void enter(cl_program *program,
                 cl_uint *numDevices,
                 const cl_device_id **deviceList,
                 const char **options,
                 cl_uint *numInputHeaders,
                 const cl_program **inputHeaders,
                 const char ***headerIncludeNames,
                 void(CL_CALLBACK **funcNotify)(cl_program program, void *userData),
                 void **userData) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.program = program;
          params.numDevices = numDevices;
          params.deviceList = deviceList;
          params.options = options;
          params.numInputHeaders = numInputHeaders;
          params.inputHeaders = inputHeaders;
          params.headerIncludeNames = headerIncludeNames;
          params.funcNotify = funcNotify;
          params.userData = userData;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCompileProgram";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCompileProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCompileProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCompileProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCompileProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCompileProgramTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCompileProgram params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateBufferTracer {
    public:
      clCreateBufferTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 size_t *size,
                 void **hostPtr,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.size = size;
          params.hostPtr = hostPtr;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateBuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateBufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateBuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateCommandQueueTracer {
    public:
      clCreateCommandQueueTracer() {}
  
      void enter(cl_context *context,
                 cl_device_id *device,
                 cl_command_queue_properties *properties,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.device = device;
          params.properties = properties;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateCommandQueue";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateCommandQueue)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateCommandQueue, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_command_queue *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateCommandQueue)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateCommandQueue, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateCommandQueueTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateCommandQueue params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateCommandQueueWithPropertiesTracer {
    public:
      clCreateCommandQueueWithPropertiesTracer() {}
  
      void enter(cl_context *context,
                 cl_device_id *device,
                 const cl_queue_properties **properties,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.device = device;
          params.properties = properties;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateCommandQueueWithProperties";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateCommandQueueWithProperties)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateCommandQueueWithProperties, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_command_queue *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateCommandQueueWithProperties)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateCommandQueueWithProperties, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateCommandQueueWithPropertiesTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateCommandQueueWithProperties params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateContextTracer {
    public:
      clCreateContextTracer() {}
  
      void enter(const cl_context_properties **properties,
                 cl_uint *numDevices,
                 const cl_device_id **devices,
                 void(CL_CALLBACK **funcNotify)(const char *, const void *, size_t, void *),
                 void **userData,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.properties = properties;
          params.numDevices = numDevices;
          params.devices = devices;
          params.funcNotify = funcNotify;
          params.userData = userData;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateContext";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateContext)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateContext, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_context *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateContext)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateContext, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateContextTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateContext params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateContextFromTypeTracer {
    public:
      clCreateContextFromTypeTracer() {}
  
      void enter(const cl_context_properties **properties,
                 cl_device_type *deviceType,
                 void(CL_CALLBACK **funcNotify)(const char *, const void *, size_t, void *),
                 void **userData,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.properties = properties;
          params.deviceType = deviceType;
          params.funcNotify = funcNotify;
          params.userData = userData;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateContextFromType";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateContextFromType)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateContextFromType, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_context *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateContextFromType)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateContextFromType, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateContextFromTypeTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateContextFromType params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateImageTracer {
    public:
      clCreateImageTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 const cl_image_format **imageFormat,
                 const cl_image_desc **imageDesc,
                 void **hostPtr,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.imageFormat = imageFormat;
          params.imageDesc = imageDesc;
          params.hostPtr = hostPtr;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateImage";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateImageTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateImage params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateImage2DTracer {
    public:
      clCreateImage2DTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 const cl_image_format **imageFormat,
                 size_t *imageWidth,
                 size_t *imageHeight,
                 size_t *imageRowPitch,
                 void **hostPtr,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.imageFormat = imageFormat;
          params.imageWidth = imageWidth;
          params.imageHeight = imageHeight;
          params.imageRowPitch = imageRowPitch;
          params.hostPtr = hostPtr;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateImage2D";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateImage2D)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateImage2D, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateImage2D)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateImage2D, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateImage2DTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateImage2D params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateImage3DTracer {
    public:
      clCreateImage3DTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 const cl_image_format **imageFormat,
                 size_t *imageWidth,
                 size_t *imageHeight,
                 size_t *imageDepth,
                 size_t *imageRowPitch,
                 size_t *imageSlicePitch,
                 void **hostPtr,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.imageFormat = imageFormat;
          params.imageWidth = imageWidth;
          params.imageHeight = imageHeight;
          params.imageDepth = imageDepth;
          params.imageRowPitch = imageRowPitch;
          params.imageSlicePitch = imageSlicePitch;
          params.hostPtr = hostPtr;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateImage3D";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateImage3D)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateImage3D, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateImage3D)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateImage3D, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateImage3DTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateImage3D params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateKernelTracer {
    public:
      clCreateKernelTracer() {}
  
      void enter(cl_program *program,
                 const char **kernelName,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.program = program;
          params.kernelName = kernelName;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateKernel";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_kernel *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateKernelTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateKernel params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateKernelsInProgramTracer {
    public:
      clCreateKernelsInProgramTracer() {}
  
      void enter(cl_program *program,
                 cl_uint *numKernels,
                 cl_kernel **kernels,
                 cl_uint **numKernelsRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.program = program;
          params.numKernels = numKernels;
          params.kernels = kernels;
          params.numKernelsRet = numKernelsRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateKernelsInProgram";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateKernelsInProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateKernelsInProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateKernelsInProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateKernelsInProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateKernelsInProgramTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateKernelsInProgram params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreatePipeTracer {
    public:
      clCreatePipeTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 cl_uint *pipePacketSize,
                 cl_uint *pipeMaxPackets,
                 const cl_pipe_properties **properties,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.pipePacketSize = pipePacketSize;
          params.pipeMaxPackets = pipeMaxPackets;
          params.properties = properties;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreatePipe";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreatePipe)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreatePipe, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreatePipe)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreatePipe, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreatePipeTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreatePipe params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateProgramWithBinaryTracer {
    public:
      clCreateProgramWithBinaryTracer() {}
  
      void enter(cl_context *context,
                 cl_uint *numDevices,
                 const cl_device_id **deviceList,
                 const size_t **lengths,
                 const unsigned char ***binaries,
                 cl_int **binaryStatus,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.numDevices = numDevices;
          params.deviceList = deviceList;
          params.lengths = lengths;
          params.binaries = binaries;
          params.binaryStatus = binaryStatus;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateProgramWithBinary";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateProgramWithBinary)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateProgramWithBinary, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_program *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateProgramWithBinary)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateProgramWithBinary, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateProgramWithBinaryTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateProgramWithBinary params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateProgramWithBuiltInKernelsTracer {
    public:
      clCreateProgramWithBuiltInKernelsTracer() {}
  
      void enter(cl_context *context,
                 cl_uint *numDevices,
                 const cl_device_id **deviceList,
                 const char **kernelNames,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.numDevices = numDevices;
          params.deviceList = deviceList;
          params.kernelNames = kernelNames;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateProgramWithBuiltInKernels";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateProgramWithBuiltInKernels)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateProgramWithBuiltInKernels, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_program *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateProgramWithBuiltInKernels)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateProgramWithBuiltInKernels, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateProgramWithBuiltInKernelsTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateProgramWithBuiltInKernels params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateProgramWithILTracer {
    public:
      clCreateProgramWithILTracer() {}
  
      void enter(cl_context *context,
                 const void **il,
                 size_t *length,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.il = il;
          params.length = length;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateProgramWithIL";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateProgramWithIL)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateProgramWithIL, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_program *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateProgramWithIL)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateProgramWithIL, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateProgramWithILTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateProgramWithIL params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateProgramWithSourceTracer {
    public:
      clCreateProgramWithSourceTracer() {}
  
      void enter(cl_context *context,
                 cl_uint *count,
                 const char ***strings,
                 const size_t **lengths,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.count = count;
          params.strings = strings;
          params.lengths = lengths;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateProgramWithSource";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateProgramWithSource)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateProgramWithSource, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_program *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateProgramWithSource)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateProgramWithSource, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateProgramWithSourceTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateProgramWithSource params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateSamplerTracer {
    public:
      clCreateSamplerTracer() {}
  
      void enter(cl_context *context,
                 cl_bool *normalizedCoords,
                 cl_addressing_mode *addressingMode,
                 cl_filter_mode *filterMode,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.normalizedCoords = normalizedCoords;
          params.addressingMode = addressingMode;
          params.filterMode = filterMode;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateSampler";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateSampler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateSampler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_sampler *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateSampler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateSampler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateSamplerTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateSampler params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateSamplerWithPropertiesTracer {
    public:
      clCreateSamplerWithPropertiesTracer() {}
  
      void enter(cl_context *context,
                 const cl_sampler_properties **samplerProperties,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.samplerProperties = samplerProperties;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateSamplerWithProperties";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateSamplerWithProperties)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateSamplerWithProperties, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_sampler *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateSamplerWithProperties)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateSamplerWithProperties, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateSamplerWithPropertiesTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateSamplerWithProperties params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateSubBufferTracer {
    public:
      clCreateSubBufferTracer() {}
  
      void enter(cl_mem *buffer,
                 cl_mem_flags *flags,
                 cl_buffer_create_type *bufferCreateType,
                 const void **bufferCreateInfo,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.buffer = buffer;
          params.flags = flags;
          params.bufferCreateType = bufferCreateType;
          params.bufferCreateInfo = bufferCreateInfo;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateSubBuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateSubBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateSubBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateSubBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateSubBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateSubBufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateSubBuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateUserEventTracer {
    public:
      clCreateUserEventTracer() {}
  
      void enter(cl_context *context,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateUserEvent";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateUserEvent)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateUserEvent, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_event *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateUserEvent)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateUserEvent, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateUserEventTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateUserEvent params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueBarrierTracer {
    public:
      clEnqueueBarrierTracer() {}
  
      void enter(cl_command_queue *commandQueue) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueBarrier";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueBarrier)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueBarrier, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueBarrier)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueBarrier, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueBarrierTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueBarrier params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueBarrierWithWaitListTracer {
    public:
      clEnqueueBarrierWithWaitListTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueBarrierWithWaitList";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueBarrierWithWaitList)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueBarrierWithWaitList, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueBarrierWithWaitList)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueBarrierWithWaitList, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueBarrierWithWaitListTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueBarrierWithWaitList params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueCopyBufferTracer {
    public:
      clEnqueueCopyBufferTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *srcBuffer,
                 cl_mem *dstBuffer,
                 size_t *srcOffset,
                 size_t *dstOffset,
                 size_t *cb,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.srcBuffer = srcBuffer;
          params.dstBuffer = dstBuffer;
          params.srcOffset = srcOffset;
          params.dstOffset = dstOffset;
          params.cb = cb;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueCopyBuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueCopyBufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueCopyBuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueCopyBufferRectTracer {
    public:
      clEnqueueCopyBufferRectTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *srcBuffer,
                 cl_mem *dstBuffer,
                 const size_t **srcOrigin,
                 const size_t **dstOrigin,
                 const size_t **region,
                 size_t *srcRowPitch,
                 size_t *srcSlicePitch,
                 size_t *dstRowPitch,
                 size_t *dstSlicePitch,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.srcBuffer = srcBuffer;
          params.dstBuffer = dstBuffer;
          params.srcOrigin = srcOrigin;
          params.dstOrigin = dstOrigin;
          params.region = region;
          params.srcRowPitch = srcRowPitch;
          params.srcSlicePitch = srcSlicePitch;
          params.dstRowPitch = dstRowPitch;
          params.dstSlicePitch = dstSlicePitch;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueCopyBufferRect";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyBufferRect)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyBufferRect, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyBufferRect)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyBufferRect, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueCopyBufferRectTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueCopyBufferRect params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueCopyBufferToImageTracer {
    public:
      clEnqueueCopyBufferToImageTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *srcBuffer,
                 cl_mem *dstImage,
                 size_t *srcOffset,
                 const size_t **dstOrigin,
                 const size_t **region,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.srcBuffer = srcBuffer;
          params.dstImage = dstImage;
          params.srcOffset = srcOffset;
          params.dstOrigin = dstOrigin;
          params.region = region;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueCopyBufferToImage";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyBufferToImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyBufferToImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyBufferToImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyBufferToImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueCopyBufferToImageTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueCopyBufferToImage params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueCopyImageTracer {
    public:
      clEnqueueCopyImageTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *srcImage,
                 cl_mem *dstImage,
                 const size_t **srcOrigin,
                 const size_t **dstOrigin,
                 const size_t **region,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.srcImage = srcImage;
          params.dstImage = dstImage;
          params.srcOrigin = srcOrigin;
          params.dstOrigin = dstOrigin;
          params.region = region;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueCopyImage";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueCopyImageTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueCopyImage params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueCopyImageToBufferTracer {
    public:
      clEnqueueCopyImageToBufferTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *srcImage,
                 cl_mem *dstBuffer,
                 const size_t **srcOrigin,
                 const size_t **region,
                 size_t *dstOffset,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.srcImage = srcImage;
          params.dstBuffer = dstBuffer;
          params.srcOrigin = srcOrigin;
          params.region = region;
          params.dstOffset = dstOffset;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueCopyImageToBuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyImageToBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyImageToBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueCopyImageToBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueCopyImageToBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueCopyImageToBufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueCopyImageToBuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueFillBufferTracer {
    public:
      clEnqueueFillBufferTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *buffer,
                 const void **pattern,
                 size_t *patternSize,
                 size_t *offset,
                 size_t *size,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.buffer = buffer;
          params.pattern = pattern;
          params.patternSize = patternSize;
          params.offset = offset;
          params.size = size;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueFillBuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueFillBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueFillBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueFillBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueFillBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueFillBufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueFillBuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueFillImageTracer {
    public:
      clEnqueueFillImageTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *image,
                 const void **fillColor,
                 const size_t **origin,
                 const size_t **region,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.image = image;
          params.fillColor = fillColor;
          params.origin = origin;
          params.region = region;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueFillImage";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueFillImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueFillImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueFillImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueFillImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueFillImageTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueFillImage params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueMapBufferTracer {
    public:
      clEnqueueMapBufferTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *buffer,
                 cl_bool *blockingMap,
                 cl_map_flags *mapFlags,
                 size_t *offset,
                 size_t *cb,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.buffer = buffer;
          params.blockingMap = blockingMap;
          params.mapFlags = mapFlags;
          params.offset = offset;
          params.cb = cb;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueMapBuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMapBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMapBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(void **retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMapBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMapBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueMapBufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueMapBuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueMapImageTracer {
    public:
      clEnqueueMapImageTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *image,
                 cl_bool *blockingMap,
                 cl_map_flags *mapFlags,
                 const size_t **origin,
                 const size_t **region,
                 size_t **imageRowPitch,
                 size_t **imageSlicePitch,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.image = image;
          params.blockingMap = blockingMap;
          params.mapFlags = mapFlags;
          params.origin = origin;
          params.region = region;
          params.imageRowPitch = imageRowPitch;
          params.imageSlicePitch = imageSlicePitch;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueMapImage";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMapImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMapImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(void **retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMapImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMapImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueMapImageTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueMapImage params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueMarkerTracer {
    public:
      clEnqueueMarkerTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueMarker";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMarker)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMarker, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMarker)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMarker, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueMarkerTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueMarker params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueMarkerWithWaitListTracer {
    public:
      clEnqueueMarkerWithWaitListTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueMarkerWithWaitList";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMarkerWithWaitList)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMarkerWithWaitList, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMarkerWithWaitList)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMarkerWithWaitList, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueMarkerWithWaitListTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueMarkerWithWaitList params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueMigrateMemObjectsTracer {
    public:
      clEnqueueMigrateMemObjectsTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_uint *numMemObjects,
                 const cl_mem **memObjects,
                 cl_mem_migration_flags *flags,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.numMemObjects = numMemObjects;
          params.memObjects = memObjects;
          params.flags = flags;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueMigrateMemObjects";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMigrateMemObjects)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMigrateMemObjects, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueMigrateMemObjects)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueMigrateMemObjects, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueMigrateMemObjectsTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueMigrateMemObjects params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueNDRangeKernelTracer {
    public:
      clEnqueueNDRangeKernelTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_kernel *kernel,
                 cl_uint *workDim,
                 const size_t **globalWorkOffset,
                 const size_t **globalWorkSize,
                 const size_t **localWorkSize,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.kernel = kernel;
          params.workDim = workDim;
          params.globalWorkOffset = globalWorkOffset;
          params.globalWorkSize = globalWorkSize;
          params.localWorkSize = localWorkSize;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueNDRangeKernel";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueNDRangeKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueNDRangeKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueNDRangeKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueNDRangeKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueNDRangeKernelTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueNDRangeKernel params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueNativeKernelTracer {
    public:
      clEnqueueNativeKernelTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 void(CL_CALLBACK **userFunc)(void *),
                 void **args,
                 size_t *cbArgs,
                 cl_uint *numMemObjects,
                 const cl_mem **memList,
                 const void ***argsMemLoc,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.userFunc = userFunc;
          params.args = args;
          params.cbArgs = cbArgs;
          params.numMemObjects = numMemObjects;
          params.memList = memList;
          params.argsMemLoc = argsMemLoc;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueNativeKernel";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueNativeKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueNativeKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueNativeKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueNativeKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueNativeKernelTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueNativeKernel params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueReadBufferTracer {
    public:
      clEnqueueReadBufferTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *buffer,
                 cl_bool *blockingRead,
                 size_t *offset,
                 size_t *cb,
                 void **ptr,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.buffer = buffer;
          params.blockingRead = blockingRead;
          params.offset = offset;
          params.cb = cb;
          params.ptr = ptr;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueReadBuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueReadBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueReadBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueReadBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueReadBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueReadBufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueReadBuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueReadBufferRectTracer {
    public:
      clEnqueueReadBufferRectTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *buffer,
                 cl_bool *blockingRead,
                 const size_t **bufferOrigin,
                 const size_t **hostOrigin,
                 const size_t **region,
                 size_t *bufferRowPitch,
                 size_t *bufferSlicePitch,
                 size_t *hostRowPitch,
                 size_t *hostSlicePitch,
                 void **ptr,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.buffer = buffer;
          params.blockingRead = blockingRead;
          params.bufferOrigin = bufferOrigin;
          params.hostOrigin = hostOrigin;
          params.region = region;
          params.bufferRowPitch = bufferRowPitch;
          params.bufferSlicePitch = bufferSlicePitch;
          params.hostRowPitch = hostRowPitch;
          params.hostSlicePitch = hostSlicePitch;
          params.ptr = ptr;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueReadBufferRect";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueReadBufferRect)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueReadBufferRect, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueReadBufferRect)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueReadBufferRect, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueReadBufferRectTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueReadBufferRect params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueReadImageTracer {
    public:
      clEnqueueReadImageTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *image,
                 cl_bool *blockingRead,
                 const size_t **origin,
                 const size_t **region,
                 size_t *rowPitch,
                 size_t *slicePitch,
                 void **ptr,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.image = image;
          params.blockingRead = blockingRead;
          params.origin = origin;
          params.region = region;
          params.rowPitch = rowPitch;
          params.slicePitch = slicePitch;
          params.ptr = ptr;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueReadImage";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueReadImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueReadImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueReadImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueReadImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueReadImageTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueReadImage params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueSVMFreeTracer {
    public:
      clEnqueueSVMFreeTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_uint *numSvmPointers,
                 void ***svmPointers,
                 void(CL_CALLBACK **pfnFreeFunc)(cl_command_queue queue, cl_uint numSvmPointers, void **svmPointers, void *userData),
                 void **userData,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.numSvmPointers = numSvmPointers;
          params.svmPointers = svmPointers;
          params.pfnFreeFunc = pfnFreeFunc;
          params.userData = userData;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueSVMFree";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMFree)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMFree, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMFree)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMFree, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueSVMFreeTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueSVMFree params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueSVMMapTracer {
    public:
      clEnqueueSVMMapTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_bool *blockingMap,
                 cl_map_flags *mapFlags,
                 void **svmPtr,
                 size_t *size,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.blockingMap = blockingMap;
          params.mapFlags = mapFlags;
          params.svmPtr = svmPtr;
          params.size = size;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueSVMMap";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMMap)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMMap, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMMap)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMMap, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueSVMMapTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueSVMMap params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueSVMMemFillTracer {
    public:
      clEnqueueSVMMemFillTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 void **svmPtr,
                 const void **pattern,
                 size_t *patternSize,
                 size_t *size,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.svmPtr = svmPtr;
          params.pattern = pattern;
          params.patternSize = patternSize;
          params.size = size;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueSVMMemFill";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMMemFill)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMMemFill, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMMemFill)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMMemFill, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueSVMMemFillTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueSVMMemFill params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueSVMMemcpyTracer {
    public:
      clEnqueueSVMMemcpyTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_bool *blockingCopy,
                 void **dstPtr,
                 const void **srcPtr,
                 size_t *size,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.blockingCopy = blockingCopy;
          params.dstPtr = dstPtr;
          params.srcPtr = srcPtr;
          params.size = size;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueSVMMemcpy";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMMemcpy)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMMemcpy, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMMemcpy)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMMemcpy, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueSVMMemcpyTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueSVMMemcpy params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueSVMMigrateMemTracer {
    public:
      clEnqueueSVMMigrateMemTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_uint *numSvmPointers,
                 const void ***svmPointers,
                 const size_t **sizes,
                 const cl_mem_migration_flags *flags,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.numSvmPointers = numSvmPointers;
          params.svmPointers = svmPointers;
          params.sizes = sizes;
          params.flags = flags;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueSVMMigrateMem";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMMigrateMem)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMMigrateMem, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMMigrateMem)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMMigrateMem, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueSVMMigrateMemTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueSVMMigrateMem params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueSVMUnmapTracer {
    public:
      clEnqueueSVMUnmapTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 void **svmPtr,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.svmPtr = svmPtr;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueSVMUnmap";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMUnmap)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMUnmap, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueSVMUnmap)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueSVMUnmap, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueSVMUnmapTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueSVMUnmap params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueTaskTracer {
    public:
      clEnqueueTaskTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_kernel *kernel,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.kernel = kernel;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueTask";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueTask)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueTask, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueTask)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueTask, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueTaskTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueTask params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueUnmapMemObjectTracer {
    public:
      clEnqueueUnmapMemObjectTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *memobj,
                 void **mappedPtr,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.memobj = memobj;
          params.mappedPtr = mappedPtr;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueUnmapMemObject";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueUnmapMemObject)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueUnmapMemObject, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueUnmapMemObject)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueUnmapMemObject, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueUnmapMemObjectTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueUnmapMemObject params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueWaitForEventsTracer {
    public:
      clEnqueueWaitForEventsTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_uint *numEvents,
                 const cl_event **eventList) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.numEvents = numEvents;
          params.eventList = eventList;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueWaitForEvents";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueWaitForEvents)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueWaitForEvents, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueWaitForEvents)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueWaitForEvents, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueWaitForEventsTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueWaitForEvents params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueWriteBufferTracer {
    public:
      clEnqueueWriteBufferTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *buffer,
                 cl_bool *blockingWrite,
                 size_t *offset,
                 size_t *cb,
                 const void **ptr,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.buffer = buffer;
          params.blockingWrite = blockingWrite;
          params.offset = offset;
          params.cb = cb;
          params.ptr = ptr;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueWriteBuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueWriteBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueWriteBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueWriteBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueWriteBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueWriteBufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueWriteBuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueWriteBufferRectTracer {
    public:
      clEnqueueWriteBufferRectTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *buffer,
                 cl_bool *blockingWrite,
                 const size_t **bufferOrigin,
                 const size_t **hostOrigin,
                 const size_t **region,
                 size_t *bufferRowPitch,
                 size_t *bufferSlicePitch,
                 size_t *hostRowPitch,
                 size_t *hostSlicePitch,
                 const void **ptr,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.buffer = buffer;
          params.blockingWrite = blockingWrite;
          params.bufferOrigin = bufferOrigin;
          params.hostOrigin = hostOrigin;
          params.region = region;
          params.bufferRowPitch = bufferRowPitch;
          params.bufferSlicePitch = bufferSlicePitch;
          params.hostRowPitch = hostRowPitch;
          params.hostSlicePitch = hostSlicePitch;
          params.ptr = ptr;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueWriteBufferRect";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueWriteBufferRect)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueWriteBufferRect, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueWriteBufferRect)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueWriteBufferRect, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueWriteBufferRectTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueWriteBufferRect params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueWriteImageTracer {
    public:
      clEnqueueWriteImageTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_mem *image,
                 cl_bool *blockingWrite,
                 const size_t **origin,
                 const size_t **region,
                 size_t *inputRowPitch,
                 size_t *inputSlicePitch,
                 const void **ptr,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.image = image;
          params.blockingWrite = blockingWrite;
          params.origin = origin;
          params.region = region;
          params.inputRowPitch = inputRowPitch;
          params.inputSlicePitch = inputSlicePitch;
          params.ptr = ptr;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueWriteImage";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueWriteImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueWriteImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueWriteImage)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueWriteImage, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueWriteImageTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueWriteImage params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clFinishTracer {
    public:
      clFinishTracer() {}
  
      void enter(cl_command_queue *commandQueue) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clFinish";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clFinish)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clFinish, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clFinish)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clFinish, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clFinishTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clFinish params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clFlushTracer {
    public:
      clFlushTracer() {}
  
      void enter(cl_command_queue *commandQueue) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clFlush";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clFlush)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clFlush, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clFlush)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clFlush, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clFlushTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clFlush params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetCommandQueueInfoTracer {
    public:
      clGetCommandQueueInfoTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_command_queue_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetCommandQueueInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetCommandQueueInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetCommandQueueInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetCommandQueueInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetCommandQueueInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetCommandQueueInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetCommandQueueInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetContextInfoTracer {
    public:
      clGetContextInfoTracer() {}
  
      void enter(cl_context *context,
                 cl_context_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetContextInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetContextInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetContextInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetContextInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetContextInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetContextInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetContextInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetDeviceAndHostTimerTracer {
    public:
      clGetDeviceAndHostTimerTracer() {}
  
      void enter(cl_device_id *device,
                 cl_ulong **deviceTimestamp,
                 cl_ulong **hostTimestamp) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.device = device;
          params.deviceTimestamp = deviceTimestamp;
          params.hostTimestamp = hostTimestamp;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetDeviceAndHostTimer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetDeviceAndHostTimer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetDeviceAndHostTimer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetDeviceAndHostTimer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetDeviceAndHostTimer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetDeviceAndHostTimerTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetDeviceAndHostTimer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetDeviceIDsTracer {
    public:
      clGetDeviceIDsTracer() {}
  
      void enter(cl_platform_id *platform,
                 cl_device_type *deviceType,
                 cl_uint *numEntries,
                 cl_device_id **devices,
                 cl_uint **numDevices) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.platform = platform;
          params.deviceType = deviceType;
          params.numEntries = numEntries;
          params.devices = devices;
          params.numDevices = numDevices;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetDeviceIDs";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetDeviceIDs)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetDeviceIDs, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetDeviceIDs)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetDeviceIDs, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetDeviceIDsTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetDeviceIDs params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetDeviceInfoTracer {
    public:
      clGetDeviceInfoTracer() {}
  
      void enter(cl_device_id *device,
                 cl_device_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.device = device;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetDeviceInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetDeviceInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetDeviceInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetDeviceInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetDeviceInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetDeviceInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetDeviceInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetEventInfoTracer {
    public:
      clGetEventInfoTracer() {}
  
      void enter(cl_event *event,
                 cl_event_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.event = event;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetEventInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetEventInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetEventInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetEventInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetEventInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetEventInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetEventInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetEventProfilingInfoTracer {
    public:
      clGetEventProfilingInfoTracer() {}
  
      void enter(cl_event *event,
                 cl_profiling_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.event = event;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetEventProfilingInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetEventProfilingInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetEventProfilingInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetEventProfilingInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetEventProfilingInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetEventProfilingInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetEventProfilingInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetExtensionFunctionAddressTracer {
    public:
      clGetExtensionFunctionAddressTracer() {}
  
      void enter(const char **funcName) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.funcName = funcName;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetExtensionFunctionAddress";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetExtensionFunctionAddress)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetExtensionFunctionAddress, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(void **retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetExtensionFunctionAddress)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetExtensionFunctionAddress, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetExtensionFunctionAddressTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetExtensionFunctionAddress params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetExtensionFunctionAddressForPlatformTracer {
    public:
      clGetExtensionFunctionAddressForPlatformTracer() {}
  
      void enter(cl_platform_id *platform,
                 const char **funcName) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.platform = platform;
          params.funcName = funcName;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetExtensionFunctionAddressForPlatform";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetExtensionFunctionAddressForPlatform)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetExtensionFunctionAddressForPlatform, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(void **retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetExtensionFunctionAddressForPlatform)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetExtensionFunctionAddressForPlatform, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetExtensionFunctionAddressForPlatformTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetExtensionFunctionAddressForPlatform params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetHostTimerTracer {
    public:
      clGetHostTimerTracer() {}
  
      void enter(cl_device_id *device,
                 cl_ulong **hostTimestamp) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.device = device;
          params.hostTimestamp = hostTimestamp;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetHostTimer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetHostTimer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetHostTimer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetHostTimer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetHostTimer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetHostTimerTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetHostTimer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetImageInfoTracer {
    public:
      clGetImageInfoTracer() {}
  
      void enter(cl_mem *image,
                 cl_image_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.image = image;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetImageInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetImageInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetImageInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetImageInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetImageInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetImageInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetImageInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetKernelArgInfoTracer {
    public:
      clGetKernelArgInfoTracer() {}
  
      void enter(cl_kernel *kernel,
                 cl_uint *argIndx,
                 cl_kernel_arg_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.kernel = kernel;
          params.argIndx = argIndx;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetKernelArgInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetKernelArgInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetKernelArgInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetKernelArgInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetKernelArgInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetKernelArgInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetKernelArgInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetKernelInfoTracer {
    public:
      clGetKernelInfoTracer() {}
  
      void enter(cl_kernel *kernel,
                 cl_kernel_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.kernel = kernel;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetKernelInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetKernelInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetKernelInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetKernelInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetKernelInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetKernelInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetKernelInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetKernelSubGroupInfoTracer {
    public:
      clGetKernelSubGroupInfoTracer() {}
  
      void enter(cl_kernel *kernel,
                 cl_device_id *device,
                 cl_kernel_sub_group_info *paramName,
                 size_t *inputValueSize,
                 const void **inputValue,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.kernel = kernel;
          params.device = device;
          params.paramName = paramName;
          params.inputValueSize = inputValueSize;
          params.inputValue = inputValue;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetKernelSubGroupInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetKernelSubGroupInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetKernelSubGroupInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetKernelSubGroupInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetKernelSubGroupInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetKernelSubGroupInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetKernelSubGroupInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetKernelWorkGroupInfoTracer {
    public:
      clGetKernelWorkGroupInfoTracer() {}
  
      void enter(cl_kernel *kernel,
                 cl_device_id *device,
                 cl_kernel_work_group_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.kernel = kernel;
          params.device = device;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetKernelWorkGroupInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetKernelWorkGroupInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetKernelWorkGroupInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetKernelWorkGroupInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetKernelWorkGroupInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetKernelWorkGroupInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetKernelWorkGroupInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetMemObjectInfoTracer {
    public:
      clGetMemObjectInfoTracer() {}
  
      void enter(cl_mem *memobj,
                 cl_mem_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.memobj = memobj;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetMemObjectInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetMemObjectInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetMemObjectInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetMemObjectInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetMemObjectInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetMemObjectInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetMemObjectInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetPipeInfoTracer {
    public:
      clGetPipeInfoTracer() {}
  
      void enter(cl_mem *pipe,
                 cl_pipe_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.pipe = pipe;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetPipeInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetPipeInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetPipeInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetPipeInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetPipeInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetPipeInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetPipeInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetPlatformIDsTracer {
    public:
      clGetPlatformIDsTracer() {}
  
      void enter(cl_uint *numEntries,
                 cl_platform_id **platforms,
                 cl_uint **numPlatforms) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.numEntries = numEntries;
          params.platforms = platforms;
          params.numPlatforms = numPlatforms;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetPlatformIDs";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetPlatformIDs)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetPlatformIDs, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetPlatformIDs)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetPlatformIDs, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetPlatformIDsTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetPlatformIDs params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetPlatformInfoTracer {
    public:
      clGetPlatformInfoTracer() {}
  
      void enter(cl_platform_id *platform,
                 cl_platform_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.platform = platform;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetPlatformInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetPlatformInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetPlatformInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetPlatformInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetPlatformInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetPlatformInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetPlatformInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetProgramBuildInfoTracer {
    public:
      clGetProgramBuildInfoTracer() {}
  
      void enter(cl_program *program,
                 cl_device_id *device,
                 cl_program_build_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.program = program;
          params.device = device;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetProgramBuildInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetProgramBuildInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetProgramBuildInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetProgramBuildInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetProgramBuildInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetProgramBuildInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetProgramBuildInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetProgramInfoTracer {
    public:
      clGetProgramInfoTracer() {}
  
      void enter(cl_program *program,
                 cl_program_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.program = program;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetProgramInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetProgramInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetProgramInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetProgramInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetProgramInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetProgramInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetProgramInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetSamplerInfoTracer {
    public:
      clGetSamplerInfoTracer() {}
  
      void enter(cl_sampler *sampler,
                 cl_sampler_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.sampler = sampler;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetSamplerInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetSamplerInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetSamplerInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetSamplerInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetSamplerInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetSamplerInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetSamplerInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetSupportedImageFormatsTracer {
    public:
      clGetSupportedImageFormatsTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 cl_mem_object_type *imageType,
                 cl_uint *numEntries,
                 cl_image_format **imageFormats,
                 cl_uint **numImageFormats) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.imageType = imageType;
          params.numEntries = numEntries;
          params.imageFormats = imageFormats;
          params.numImageFormats = numImageFormats;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetSupportedImageFormats";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetSupportedImageFormats)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetSupportedImageFormats, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetSupportedImageFormats)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetSupportedImageFormats, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetSupportedImageFormatsTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetSupportedImageFormats params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clLinkProgramTracer {
    public:
      clLinkProgramTracer() {}
  
      void enter(cl_context *context,
                 cl_uint *numDevices,
                 const cl_device_id **deviceList,
                 const char **options,
                 cl_uint *numInputPrograms,
                 const cl_program **inputPrograms,
                 void(CL_CALLBACK **funcNotify)(cl_program program, void *userData),
                 void **userData,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.numDevices = numDevices;
          params.deviceList = deviceList;
          params.options = options;
          params.numInputPrograms = numInputPrograms;
          params.inputPrograms = inputPrograms;
          params.funcNotify = funcNotify;
          params.userData = userData;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clLinkProgram";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clLinkProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clLinkProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_program *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clLinkProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clLinkProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clLinkProgramTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clLinkProgram params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clReleaseCommandQueueTracer {
    public:
      clReleaseCommandQueueTracer() {}
  
      void enter(cl_command_queue *commandQueue) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clReleaseCommandQueue";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseCommandQueue)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseCommandQueue, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseCommandQueue)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseCommandQueue, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clReleaseCommandQueueTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clReleaseCommandQueue params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clReleaseContextTracer {
    public:
      clReleaseContextTracer() {}
  
      void enter(cl_context *context) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clReleaseContext";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseContext)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseContext, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseContext)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseContext, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clReleaseContextTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clReleaseContext params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clReleaseDeviceTracer {
    public:
      clReleaseDeviceTracer() {}
  
      void enter(cl_device_id *device) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.device = device;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clReleaseDevice";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseDevice)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseDevice, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseDevice)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseDevice, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clReleaseDeviceTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clReleaseDevice params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clReleaseEventTracer {
    public:
      clReleaseEventTracer() {}
  
      void enter(cl_event *event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clReleaseEvent";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseEvent)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseEvent, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseEvent)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseEvent, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clReleaseEventTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clReleaseEvent params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clReleaseKernelTracer {
    public:
      clReleaseKernelTracer() {}
  
      void enter(cl_kernel *kernel) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.kernel = kernel;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clReleaseKernel";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clReleaseKernelTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clReleaseKernel params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clReleaseMemObjectTracer {
    public:
      clReleaseMemObjectTracer() {}
  
      void enter(cl_mem *memobj) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.memobj = memobj;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clReleaseMemObject";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseMemObject)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseMemObject, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseMemObject)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseMemObject, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clReleaseMemObjectTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clReleaseMemObject params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clReleaseProgramTracer {
    public:
      clReleaseProgramTracer() {}
  
      void enter(cl_program *program) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.program = program;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clReleaseProgram";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clReleaseProgramTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clReleaseProgram params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clReleaseSamplerTracer {
    public:
      clReleaseSamplerTracer() {}
  
      void enter(cl_sampler *sampler) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.sampler = sampler;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clReleaseSampler";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseSampler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseSampler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clReleaseSampler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clReleaseSampler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clReleaseSamplerTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clReleaseSampler params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clRetainCommandQueueTracer {
    public:
      clRetainCommandQueueTracer() {}
  
      void enter(cl_command_queue *commandQueue) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clRetainCommandQueue";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainCommandQueue)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainCommandQueue, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainCommandQueue)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainCommandQueue, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clRetainCommandQueueTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clRetainCommandQueue params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clRetainContextTracer {
    public:
      clRetainContextTracer() {}
  
      void enter(cl_context *context) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clRetainContext";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainContext)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainContext, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainContext)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainContext, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clRetainContextTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clRetainContext params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clRetainDeviceTracer {
    public:
      clRetainDeviceTracer() {}
  
      void enter(cl_device_id *device) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.device = device;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clRetainDevice";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainDevice)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainDevice, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainDevice)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainDevice, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clRetainDeviceTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clRetainDevice params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clRetainEventTracer {
    public:
      clRetainEventTracer() {}
  
      void enter(cl_event *event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clRetainEvent";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainEvent)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainEvent, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainEvent)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainEvent, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clRetainEventTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clRetainEvent params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clRetainKernelTracer {
    public:
      clRetainKernelTracer() {}
  
      void enter(cl_kernel *kernel) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.kernel = kernel;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clRetainKernel";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainKernel)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainKernel, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clRetainKernelTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clRetainKernel params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clRetainMemObjectTracer {
    public:
      clRetainMemObjectTracer() {}
  
      void enter(cl_mem *memobj) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.memobj = memobj;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clRetainMemObject";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainMemObject)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainMemObject, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainMemObject)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainMemObject, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clRetainMemObjectTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clRetainMemObject params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clRetainProgramTracer {
    public:
      clRetainProgramTracer() {}
  
      void enter(cl_program *program) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.program = program;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clRetainProgram";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainProgram)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainProgram, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clRetainProgramTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clRetainProgram params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clRetainSamplerTracer {
    public:
      clRetainSamplerTracer() {}
  
      void enter(cl_sampler *sampler) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.sampler = sampler;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clRetainSampler";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainSampler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainSampler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clRetainSampler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clRetainSampler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clRetainSamplerTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clRetainSampler params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSVMAllocTracer {
    public:
      clSVMAllocTracer() {}
  
      void enter(cl_context *context,
                 cl_svm_mem_flags *flags,
                 size_t *size,
                 cl_uint *alignment) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.size = size;
          params.alignment = alignment;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSVMAlloc";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSVMAlloc)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSVMAlloc, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(void **retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSVMAlloc)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSVMAlloc, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSVMAllocTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSVMAlloc params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSVMFreeTracer {
    public:
      clSVMFreeTracer() {}
  
      void enter(cl_context *context,
                 void **svmPointer) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.svmPointer = svmPointer;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSVMFree";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSVMFree)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSVMFree, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(void *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSVMFree)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSVMFree, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSVMFreeTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSVMFree params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSetCommandQueuePropertyTracer {
    public:
      clSetCommandQueuePropertyTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_command_queue_properties *properties,
                 cl_bool *enable,
                 cl_command_queue_properties **oldProperties) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.properties = properties;
          params.enable = enable;
          params.oldProperties = oldProperties;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSetCommandQueueProperty";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetCommandQueueProperty)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetCommandQueueProperty, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetCommandQueueProperty)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetCommandQueueProperty, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSetCommandQueuePropertyTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSetCommandQueueProperty params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSetDefaultDeviceCommandQueueTracer {
    public:
      clSetDefaultDeviceCommandQueueTracer() {}
  
      void enter(cl_context *context,
                 cl_device_id *device,
                 cl_command_queue *commandQueue) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.device = device;
          params.commandQueue = commandQueue;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSetDefaultDeviceCommandQueue";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetDefaultDeviceCommandQueue)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetDefaultDeviceCommandQueue, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetDefaultDeviceCommandQueue)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetDefaultDeviceCommandQueue, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSetDefaultDeviceCommandQueueTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSetDefaultDeviceCommandQueue params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSetEventCallbackTracer {
    public:
      clSetEventCallbackTracer() {}
  
      void enter(cl_event *event,
                 cl_int *commandExecCallbackType,
                 void(CL_CALLBACK **funcNotify)(cl_event, cl_int, void *),
                 void **userData) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.event = event;
          params.commandExecCallbackType = commandExecCallbackType;
          params.funcNotify = funcNotify;
          params.userData = userData;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSetEventCallback";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetEventCallback)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetEventCallback, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetEventCallback)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetEventCallback, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSetEventCallbackTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSetEventCallback params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSetKernelArgTracer {
    public:
      clSetKernelArgTracer() {}
  
      void enter(cl_kernel *kernel,
                 cl_uint *argIndex,
                 size_t *argSize,
                 const void **argValue) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.kernel = kernel;
          params.argIndex = argIndex;
          params.argSize = argSize;
          params.argValue = argValue;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSetKernelArg";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetKernelArg)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetKernelArg, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetKernelArg)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetKernelArg, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSetKernelArgTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSetKernelArg params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSetKernelArgSVMPointerTracer {
    public:
      clSetKernelArgSVMPointerTracer() {}
  
      void enter(cl_kernel *kernel,
                 cl_uint *argIndex,
                 const void **argValue) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.kernel = kernel;
          params.argIndex = argIndex;
          params.argValue = argValue;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSetKernelArgSVMPointer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetKernelArgSVMPointer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetKernelArgSVMPointer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetKernelArgSVMPointer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetKernelArgSVMPointer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSetKernelArgSVMPointerTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSetKernelArgSVMPointer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSetKernelExecInfoTracer {
    public:
      clSetKernelExecInfoTracer() {}
  
      void enter(cl_kernel *kernel,
                 cl_kernel_exec_info *paramName,
                 size_t *paramValueSize,
                 const void **paramValue) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.kernel = kernel;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSetKernelExecInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetKernelExecInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetKernelExecInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetKernelExecInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetKernelExecInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSetKernelExecInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSetKernelExecInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSetMemObjectDestructorCallbackTracer {
    public:
      clSetMemObjectDestructorCallbackTracer() {}
  
      void enter(cl_mem *memobj,
                 void(CL_CALLBACK **funcNotify)(cl_mem, void *),
                 void **userData) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.memobj = memobj;
          params.funcNotify = funcNotify;
          params.userData = userData;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSetMemObjectDestructorCallback";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetMemObjectDestructorCallback)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetMemObjectDestructorCallback, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetMemObjectDestructorCallback)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetMemObjectDestructorCallback, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSetMemObjectDestructorCallbackTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSetMemObjectDestructorCallback params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clSetUserEventStatusTracer {
    public:
      clSetUserEventStatusTracer() {}
  
      void enter(cl_event *event,
                 cl_int *executionStatus) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.event = event;
          params.executionStatus = executionStatus;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clSetUserEventStatus";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetUserEventStatus)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetUserEventStatus, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clSetUserEventStatus)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clSetUserEventStatus, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clSetUserEventStatusTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clSetUserEventStatus params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clUnloadCompilerTracer {
    public:
      clUnloadCompilerTracer() {}
  
      void enter() {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clUnloadCompiler";
          data.functionParams = nullptr;
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clUnloadCompiler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clUnloadCompiler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clUnloadCompiler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clUnloadCompiler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clUnloadCompilerTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clUnloadPlatformCompilerTracer {
    public:
      clUnloadPlatformCompilerTracer() {}
  
      void enter(cl_platform_id *platform) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.platform = platform;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clUnloadPlatformCompiler";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clUnloadPlatformCompiler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clUnloadPlatformCompiler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clUnloadPlatformCompiler)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clUnloadPlatformCompiler, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clUnloadPlatformCompilerTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clUnloadPlatformCompiler params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clWaitForEventsTracer {
    public:
      clWaitForEventsTracer() {}
  
      void enter(cl_uint *numEvents,
                 const cl_event **eventList) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.numEvents = numEvents;
          params.eventList = eventList;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clWaitForEvents";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clWaitForEvents)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clWaitForEvents, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clWaitForEvents)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clWaitForEvents, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clWaitForEventsTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clWaitForEvents params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  #ifdef _WIN32
  
  class clCreateFromGLBufferTracer {
    public:
      clCreateFromGLBufferTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 cl_GLuint *bufobj,
                 int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.bufobj = bufobj;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateFromGLBuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLBuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLBuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateFromGLBufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateFromGLBuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateFromGLRenderbufferTracer {
    public:
      clCreateFromGLRenderbufferTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 cl_GLuint *renderbuffer,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.renderbuffer = renderbuffer;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateFromGLRenderbuffer";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLRenderbuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLRenderbuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLRenderbuffer)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLRenderbuffer, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateFromGLRenderbufferTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateFromGLRenderbuffer params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateFromGLTextureTracer {
    public:
      clCreateFromGLTextureTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 cl_GLenum *target,
                 cl_GLint *miplevel,
                 cl_GLuint *texture,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.target = target;
          params.miplevel = miplevel;
          params.texture = texture;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateFromGLTexture";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLTexture)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLTexture, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLTexture)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLTexture, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateFromGLTextureTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateFromGLTexture params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateFromGLTexture2DTracer {
    public:
      clCreateFromGLTexture2DTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 cl_GLenum *target,
                 cl_GLint *miplevel,
                 cl_GLuint *texture,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.target = target;
          params.miplevel = miplevel;
          params.texture = texture;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateFromGLTexture2D";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLTexture2D)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLTexture2D, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLTexture2D)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLTexture2D, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateFromGLTexture2DTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateFromGLTexture2D params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clCreateFromGLTexture3DTracer {
    public:
      clCreateFromGLTexture3DTracer() {}
  
      void enter(cl_context *context,
                 cl_mem_flags *flags,
                 cl_GLenum *target,
                 cl_GLint *miplevel,
                 cl_GLuint *texture,
                 cl_int **errcodeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.context = context;
          params.flags = flags;
          params.target = target;
          params.miplevel = miplevel;
          params.texture = texture;
          params.errcodeRet = errcodeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clCreateFromGLTexture3D";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLTexture3D)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLTexture3D, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_mem *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clCreateFromGLTexture3D)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clCreateFromGLTexture3D, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clCreateFromGLTexture3DTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clCreateFromGLTexture3D params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueAcquireGLObjectsTracer {
    public:
      clEnqueueAcquireGLObjectsTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_uint *numObjects,
                 const cl_mem **memObjects,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.numObjects = numObjects;
          params.memObjects = memObjects;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueAcquireGLObjects";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueAcquireGLObjects)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueAcquireGLObjects, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueAcquireGLObjects)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueAcquireGLObjects, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueAcquireGLObjectsTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueAcquireGLObjects params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clEnqueueReleaseGLObjectsTracer {
    public:
      clEnqueueReleaseGLObjectsTracer() {}
  
      void enter(cl_command_queue *commandQueue,
                 cl_uint *numObjects,
                 const cl_mem **memObjects,
                 cl_uint *numEventsInWaitList,
                 const cl_event **eventWaitList,
                 cl_event **event) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.commandQueue = commandQueue;
          params.numObjects = numObjects;
          params.memObjects = memObjects;
          params.numEventsInWaitList = numEventsInWaitList;
          params.eventWaitList = eventWaitList;
          params.event = event;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clEnqueueReleaseGLObjects";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueReleaseGLObjects)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueReleaseGLObjects, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clEnqueueReleaseGLObjects)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clEnqueueReleaseGLObjects, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clEnqueueReleaseGLObjectsTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clEnqueueReleaseGLObjects params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetGLObjectInfoTracer {
    public:
      clGetGLObjectInfoTracer() {}
  
      void enter(cl_mem *memobj,
                 cl_gl_object_type **glObjectType,
                 cl_GLuint **glObjectName) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.memobj = memobj;
          params.glObjectType = glObjectType;
          params.glObjectName = glObjectName;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetGLObjectInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetGLObjectInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetGLObjectInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetGLObjectInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetGLObjectInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetGLObjectInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetGLObjectInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  class clGetGLTextureInfoTracer {
    public:
      clGetGLTextureInfoTracer() {}
  
      void enter(cl_mem *memobj,
                 cl_gl_texture_info *paramName,
                 size_t *paramValueSize,
                 void **paramValue,
                 size_t **paramValueSizeRet) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED);
  
          params.memobj = memobj;
          params.paramName = paramName;
          params.paramValueSize = paramValueSize;
          params.paramValue = paramValue;
          params.paramValueSizeRet = paramValueSizeRet;
  
          data.site = CL_CALLBACK_SITE_ENTER;
          data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel);
          data.functionName = "clGetGLTextureInfo";
          data.functionParams = static_cast<const void *>(&params);
          data.functionReturnValue = nullptr;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetGLTextureInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetGLTextureInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_ENTER_CALLED;
      }
  
      void exit(cl_int *retVal) {
          DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED);
          data.site = CL_CALLBACK_SITE_EXIT;
          data.functionReturnValue = retVal;
  
          size_t i = 0;
          DEBUG_BREAK_IF(tracingHandle[0] == nullptr);
          while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) {
              TracingHandle *handle = tracingHandle[i];
              DEBUG_BREAK_IF(handle == nullptr);
              if (handle->getTracingPoint(CL_FUNCTION_clGetGLTextureInfo)) {
                  data.correlationData = correlationData + i;
                  handle->call(CL_FUNCTION_clGetGLTextureInfo, &data);
              }
              ++i;
          }
  
          state = TRACING_NOTIFY_STATE_EXIT_CALLED;
      }
  
      ~clGetGLTextureInfoTracer() {
          DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED);
      }
  
    private:
      cl_params_clGetGLTextureInfo params{};
      cl_callback_data data{};
      uint64_t correlationData[TRACING_MAX_HANDLE_COUNT];
      tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED;
  };
  
  #endif
  
  } // namespace HostSideTracing
  