#ifndef TILE_BASE_BUFFER_BUILTIN_BUFFER_BLOCK_H
#define TILE_BASE_BUFFER_BUILTIN_BUFFER_BLOCK_H

#pragma once

#include "tile/base/align.h"
#include "tile/base/buffer/polymorphic_buffer.h"
#include "tile/base/ref_ptr.h"

namespace tile {
class alignas(hardware_destructive_interference_size) NativeBufferBlock : public PolymorphicBufferBlock {
public:
    virtual char *mutable_data() noexcept = 0;
};

RefPtr<NativeBufferBlock> MakeNativeBufferBlock();

template<typename F>
class ReferencingBufferBlock : public PolymorphicBufferBlock, private F /* Empty Base Optimize */ {
public:
    explicit ReferencingBufferBlock(const void *ptr, std::size_t size, F &&completion_cb)
        : F(std::move(completion_cb)),
          ptr_(ptr),
          size_(size)
    {}

    ~ReferencingBufferBlock() override { (*this)(); }

    const char *data() const noexcept override { return reinterpret_cast<const char *>(ptr_); }

    std::size_t size() const noexcept override { return size_; }

private:
    const void *ptr_;
    std::size_t size_;
};// namespace tile
}// namespace tile

#endif// TILE_BASE_BUFFER_BUILTIN_BUFFER_BLOCK_H
