#pragma once

namespace gpucache{
    constexpr unsigned int warpFullMask = 0xFFFFFFFF;
    constexpr unsigned int defaultBlockX = 256;
    constexpr unsigned int warpSize = 32;
    constexpr unsigned int defaultNumWarpsPerBlock = defaultBlockX / warpSize;
    // bucket_id + key
    constexpr unsigned int SharedMemorySize = 2 * sizeof(uint32_t) * defaultNumWarpsPerBlock * warpSize;



    struct ThreadCtx {
        __device__ ThreadCtx();

        uint32_t global_warp_idx;
        uint32_t block_warp_idx;
        uint32_t num_warps;
        uint32_t lane_id;
    };

    struct WarpMutex {
    public:
        __device__ WarpMutex();

        ~WarpMutex() = default;

        WarpMutex(const WarpMutex &) = delete;

        WarpMutex &operator=(const WarpMutex &) = delete;

        WarpMutex(WarpMutex &&) = delete;

        WarpMutex &operator=(WarpMutex &&) = delete;

        __device__ void Lock(ThreadCtx &ctx);

        __device__ void UnLock(ThreadCtx &ctx);

        //    private:
        uint32_t flag;
    };

    __global__ void initLocks(uint32_t n_bucket, void *bucketMutexes);

    struct CacheConfig {
        enum CacheEvictStrategy {
            FIFO,
            LRU,
            LFU
        };

        CacheConfig() = default;

        CacheConfig(CacheEvictStrategy s, uint64_t cap, uint32_t key_size, uint32_t value_size,
                    uint32_t max_query_num, uint32_t device_id, uint32_t dim) :
                strategy(s), capacity(cap), key_size(key_size), value_size(value_size),
                max_query_num(max_query_num), device_id(device_id), dim(dim) {}

        CacheEvictStrategy strategy;
        uint64_t capacity;
        uint32_t key_size;
        uint32_t value_size;
        uint32_t dim;
        uint32_t max_query_num;
        uint32_t device_id;
    };



}

