d创建特定大小缓冲区指针或切片

原文
假设有包含存储内存缓冲内存管理器.
你想分发这些内存块给程序的其他部分.块大小为PAGE_SIZE.类似这样:

enum PAGE_SIZE = 4096;
enum BUF_POOL_NUM_PAGES = 1024;

class BufferPool
{
    align(PAGE_SIZE) ubyte[PAGE_SIZE * BUF_POOL_NUM_PAGES] data;

    this()
    {
        mmap(&data, data.sizeof,PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
    }
}

现在应该有个返回ubyte页大小(PAGE_SIZE)指针取页()(get_page())函数.但只知道如何返回ubyte[]:

ubyte[] get_page(frame_idx_t frame_idx)
{
    return data[frame_idx * PAGE_SIZE .. (frame_idx + 1) * PAGE_SIZE];
}

是否可返回ubyte[PAGE_SIZE]*ref ubyte[PAGE_SIZE]?

简单的转换似乎有效:

enum PAGE_SIZE = 4096;
enum BUF_POOL_NUM_PAGES = 1024;
alias frame_idx_t = size_t;

ubyte[10_000] data;

ubyte[PAGE_SIZE]* get_page(frame_idx_t frame_idx)
{
    auto ptr = data.ptr + frame_idx * PAGE_SIZE;
    return cast(ubyte[PAGE_SIZE]*)ptr;
}

void main() {
}

C++中等价版如下:

#include <cstddef>
#include <span>
#include <sys/mman.h>

static constexpr size_t PAGE_SIZE          = 4096;
static constexpr size_t BUF_POOL_NUM_PAGES = 1024;

class BufferPool
{
  private:
    alignas(PAGE_SIZE) std::byte data[BUF_POOL_NUM_PAGES * PAGE_SIZE];

  public:
    BufferPool()
    {
        mmap(data, BUF_POOL_NUM_PAGES * PAGE_SIZE,PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    }

     //返回页上包含`{T*ptr,len}`的`PAGE_SIZE`字节的胖指针
    std::span<std::byte, PAGE_SIZE> get_page(size_t page_num)
    {
        return std::span<std::byte, PAGE_SIZE>(data + page_num * PAGE_SIZE, PAGE_SIZE);
    }
};

也许在带有不变新类包装切片(.a),会更好?
因为我想:
1,确保基础引用指向的数据长度页大小(PAGE_SIZE)
2,从D的特性中获益

检查切片边界省去了开发过程中的许多麻烦.
或如下会更好?

struct Frame
{
    ubyte[] data;

    invariant
    {
        assert(data.length == PAGE_SIZE);
    }
}

class BufferPool
{
    align(PAGE_SIZE) ubyte[PAGE_SIZE * BUF_POOL_NUM_PAGES] data;
    Frame[BUF_POOL_NUM_PAGES] frames;

    this()
    {
        // mmap
        foreach (i; 0 .. BUF_POOL_NUM_PAGES)
        {
            frame_idx_t frame_idx = cast(frame_idx_t) i;
            frames[frame_idx].data = data[frame_idx * PAGE_SIZE .. (frame_idx + 1) * PAGE_SIZE];
        }
    }
}

是的,因为静态数组只是内存中并排的元素(.b).只要长度和对齐方式正确,就可按静态数组转换内存块.
但是,在@safe代码中禁止此转换.

:.a.
有可能,但使用前要检查,因为'不变'要求是成员函数:
这里
为什么不用切片呢?
注意,静态数组值类型,而且彼此为不同类型,可能导致模板膨胀.
除非需要,大多数D程序员使用.

Frame[BUF_POOL_NUM_PAGES] frames;

合理.

:.b.
更准确地说,转换内存为正确大小静态数组*指针*.静态数组是值类型,传递原始数组,会导致每次都冗余复制该数组.

posted @   zjh6  阅读(11)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示