#ifndef DTACT_H
#define DTACT_H

/* Generated with cbindgen:0.29.4 */

/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */

#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

namespace dtact {

/*
 Number of tasks in a single `TaskChunk`.
 */
constexpr static const size_t CHUNK_SIZE = 32;

/*
 Capacity of a worker's local execution queue.
 Sized to exactly hold the max queue without global locks.
 */
constexpr static const size_t LOCAL_QUEUE_CAPACITY = 131072;

/*
 High-water mark above which a worker stops accepting new chunks and routes
 them onward. Set at 7/8 capacity so `push_batch` has guaranteed headroom for
 one full chunk on top.
 */
constexpr static const size_t LOCAL_QUEUE_HIGH_WATERMARK = (LOCAL_QUEUE_CAPACITY - (LOCAL_QUEUE_CAPACITY / 8));

/*
 Mask for local queue index wrap-around.
 */
constexpr static const size_t LOCAL_QUEUE_MASK = (LOCAL_QUEUE_CAPACITY - 1);

/*
 Capacity of a single core-to-core mailbox.
 MUST be a power of two for bitwise masking.
 */
constexpr static const size_t MAILBOX_CAPACITY = 65536;

/*
 Mask for mailbox index wrap-around.
 */
constexpr static const size_t MAILBOX_MASK = (MAILBOX_CAPACITY - 1);

/*
 Warehouse capacity in chunks. 32 768 chunks × 32 tasks = 1 048 576 tasks of
 emergency back-pressure storage. Must be a power of two for bitwise masking.
 */
constexpr static const size_t WAREHOUSE_CAPACITY = 32768;

/*
 Mask for warehouse index wrap-around.
 */
constexpr static const size_t WAREHOUSE_MASK = (WAREHOUSE_CAPACITY - 1);

/*
 Opaque handle representing a spawned Dtact fiber.
 */
using dtact_handle_t = uint64_t;

/*
 Configuration structure for initializing the Dtact runtime from C.
 */
struct dtact_config_t {
    /*
     Number of hardware worker threads. Set to 0 for auto-detection.
     */
    uint32_t mWorkers;
    /*
     Memory safety level (0-2).
     */
    uint8_t mSafetyLevel;
    /*
     Topology mode (0: `P2PMesh`, 1: Global).
     */
    uint8_t mTopologyMode;
    /*
     NUMA node for memory allocation. Set to 0 for default (local node).
     */
    uint8_t mNuma;
    /*
     Maximum number of concurrent fibers. Set to 0 for default (4096).
     */
    uint32_t mFiberCapacity;
    /*
     Stack size per fiber in bytes. Set to 0 for default (512KB).
     */
    uint32_t mStackSize;

    dtact_config_t(uint32_t const& aMWorkers,
                   uint8_t const& aMSafetyLevel,
                   uint8_t const& aMTopologyMode,
                   uint8_t const& aMNuma,
                   uint32_t const& aMFiberCapacity,
                   uint32_t const& aMStackSize)
      : mWorkers(aMWorkers),
        mSafetyLevel(aMSafetyLevel),
        mTopologyMode(aMTopologyMode),
        mNuma(aMNuma),
        mFiberCapacity(aMFiberCapacity),
        mStackSize(aMStackSize)
    {}

    bool operator==(const dtact_config_t& aOther) const {
        return mWorkers == aOther.mWorkers &&
               mSafetyLevel == aOther.mSafetyLevel &&
               mTopologyMode == aOther.mTopologyMode &&
               mNuma == aOther.mNuma &&
               mFiberCapacity == aOther.mFiberCapacity &&
               mStackSize == aOther.mStackSize;
    }
    bool operator!=(const dtact_config_t& aOther) const {
        return mWorkers != aOther.mWorkers ||
               mSafetyLevel != aOther.mSafetyLevel ||
               mTopologyMode != aOther.mTopologyMode ||
               mNuma != aOther.mNuma ||
               mFiberCapacity != aOther.mFiberCapacity ||
               mStackSize != aOther.mStackSize;
    }
};

/*
 Advanced options for spawning a fiber from C FFI.
 */
struct dtact_spawn_options_t {
    /*
     0: Low, 1: Normal, 2: High, 3: Critical
     */
    uint8_t mPriority;
    /*
     0: `SameCore`, 1: `SameCCX`, 2: `SameNUMA`, 3: Any
     */
    uint8_t mAffinity;
    /*
     0: Compute, 1: IO, 2: Memory, 3: System
     */
    uint8_t mKind;
    /*
     0: `CrossThreadFloat`, 1: `CrossThreadNoFloat`, 2: `SameThreadFloat`, 3: `SameThreadNoFloat`
     */
    uint8_t mSwitcher;

    dtact_spawn_options_t(uint8_t const& aMPriority,
                          uint8_t const& aMAffinity,
                          uint8_t const& aMKind,
                          uint8_t const& aMSwitcher)
      : mPriority(aMPriority),
        mAffinity(aMAffinity),
        mKind(aMKind),
        mSwitcher(aMSwitcher)
    {}

    bool operator==(const dtact_spawn_options_t& aOther) const {
        return mPriority == aOther.mPriority &&
               mAffinity == aOther.mAffinity &&
               mKind == aOther.mKind &&
               mSwitcher == aOther.mSwitcher;
    }
    bool operator!=(const dtact_spawn_options_t& aOther) const {
        return mPriority != aOther.mPriority ||
               mAffinity != aOther.mAffinity ||
               mKind != aOther.mKind ||
               mSwitcher != aOther.mSwitcher;
    }
};

extern "C" {

/*
 Critical failure handler. Aborts the process if a fiber attempts to
 return without properly terminating via the runtime.
 */

void dtact_abort()
;

/*
 Blocks the current thread until the specified fiber terminates.

 If called from a Dtact fiber, this will natively yield the physical core.
 If called from a non-managed thread (e.g., C main), this uses a tiered
 spin-loop and futex-wait strategy for zero-CPU idling.

 # Panics
 * Panics if the runtime is not initialized.
 */

void dtact_await(dtact_handle_t aHandle)
;

/*
 Returns the recommended default configuration for the Dtact runtime.
 */

dtact_config_t dtact_default_config()
;

/*
 Returns the recommended default options for the Dtact runtime.
 */

dtact_spawn_options_t dtact_default_spawn_options()
;

/*
 Launches a C-function as a DTA-V3 stackful Fiber.

 # Safety
 * `func` must be a valid function pointer.
 * `arg` must point to memory that remains valid for the entire duration of the fiber's execution.
   Since the fiber is launched asynchronously, the caller's stack may return before the fiber starts.
   **Critical**: `arg` must be heap-allocated (and freed within the fiber) or static.

 # Panics
 * Panics if the runtime is not initialized.
 * Panics if the context pool is exhausted.
 */

dtact_handle_t dtact_fiber_launch(void (*aFunc)(void*),
                                  void *aArg)
;

/*
 Launches a C-function as a DTA-V3 stackful Fiber with advanced options.
 */

dtact_handle_t dtact_fiber_launch_ext(void (*aFunc)(void*),
                                      void *aArg,
                                      const dtact_spawn_options_t *aOptions)
;

/*
 Launches a C-function as a DTA-V3 stackful Fiber with an ownership cleanup callback.

 # Safety
 * `func` and `cleanup` must be valid function pointers.
 * `cleanup` will be called with `arg` once the fiber has finished execution.

 # Panics
 * Panics if the runtime is not initialized.
 * Panics if the context pool is exhausted.
 */

dtact_handle_t dtact_fiber_launch_with_cleanup(void (*aFunc)(void*),
                                               void *aArg,
                                               void (*aCleanup)(void*))
;

/*
 Launches a C-function as a DTA-V3 stackful Fiber with an ownership cleanup callback and options.
 */

dtact_handle_t dtact_fiber_launch_with_cleanup_ext(void (*aFunc)(void*),
                                                   void *aArg,
                                                   void (*aCleanup)(void*),
                                                   const dtact_spawn_options_t *aOptions)
;

/*
 Frees an argument pointer previously allocated for a fiber.

 # Safety
 * `arg` must be a valid pointer previously allocated by the C allocator (e.g. `malloc`).
 */

void dtact_free_arg(void *aArg)
;

/*
 Initializes the global Dtact runtime singleton.

 # Safety
 * This function should be called once at application startup.
 * `cfg` must be a valid, non-null pointer to a `dtact_config_t` structure.

 # Panics
 * Panics if the runtime is already initialized or if memory allocation fails.
 */

void *dtact_init(const dtact_config_t *aCfg)
;

/*
 Signals all worker threads to shutdown and waits for them to terminate.
 This call blocks until all hardware worker threads have exited.

 # Panics
 * Panics if the runtime is not initialized.
 */

void dtact_run(void *aRt)
;

/*
 Signals the cooperative shutdown of all Dtact worker threads.
 */

void dtact_shutdown()
;

}  // extern "C"

}  // namespace dtact

#endif  // DTACT_H
