You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
shuffle3/include/map.h

203 lines
5.3 KiB

#ifndef _MAP_H
#define _MAP_H
#ifdef __cplusplus
#include <stdexcept>
extern "C" {
#define restrict __restrict__
#define MIFCXX(y, n) y
#define MIFC(y, n) n
#else
#define MIFCXX(y, n) n
#define MIFC(y, n) y
#endif
#include <stddef.h>
typedef struct mmap {
int fd;
void* ptr;
size_t len;
} mmap_t;
enum map_flags {
MMF_SHARED,
MMF_PRIVATE,
MMF_READONLY,
};
int map_raw_fd(int fd, mmap_t* restrict ptr, const size_t MIFCXX(* sz, sz[static 1]));
int open_and_alloc(const char* file, mmap_t* restrict ptr, size_t sz);
int open_and_map(const char* file, mmap_t* restrict ptr);
int unmap_and_close(mmap_t map);
int dup_map(const mmap_t *in, mmap_t* restrict out, const size_t *new_size, enum map_flags flags) __attribute__((nonnull(1)));
int map_advise_rand(mmap_t* restrict ptr, int need);
typedef void* (*map_cb)(mmap_t map, void* user);
void* map_and_then(const char* file, map_cb callback, void* user);
void* map_fd_and_then(int fd, map_cb callback, void* user);
int unmap_and_close_s(mmap_t map, int flags);
#ifdef __cplusplus
}
#include <panic.h>
#include "reinterpret.h"
#include <cstdint>
namespace mm {
enum class Access {
Random,
};
struct mmap;
template<typename T>
concept MemMap = std::derived_from<T, mmap>
and std::is_constructible_v<T, mmap_t>;
struct mmap {
template<MemMap M = mmap>
inline static M allocate(const char* file, std::size_t sz)
{
mmap_t map;
if(!open_and_alloc(file, &map, sz)) panic("Failed to allocmap file");
return M{map};
}
inline static mmap_t create_raw(const char* file)
{
mmap_t map;
if (!::open_and_map(file, &map)) panic("Failed to map file");
return map;
}
inline static mmap_t create_raw_fd(int fd, size_t sz)
{
mmap_t map;
if (!::map_raw_fd(fd, &map, &sz)) panic("Failed to allocmap fd");
return map;
}
inline static mmap_t create_raw_fd(int fd)
{
mmap_t map;
if (!::map_raw_fd(fd, &map, nullptr)) panic("Failed to map fd");
return map;
}
template<MemMap M = mmap>
inline static M map_raw_fd(int fd, std::size_t sz = 0)
{
if(sz)
return M{fd, sz};
else return M{fd};
}
inline explicit mmap(mmap_t raw) noexcept :inner(raw){}
inline mmap(const char* file)
: inner(create_raw(file)) {}
inline mmap(mmap&& move) : inner(move.inner)
{
auto other = const_cast<mmap_t*>(&move.inner);
other->ptr = nullptr;
}
inline mmap(const mmap& copt) = delete;
inline virtual ~mmap()
{
if (inner.ptr) {
::unmap_and_close(inner);
}
}
inline virtual mmap&& access(Access a, bool need=false) && noexcept
{
if(inner.ptr)
static_cast<mmap&>(*this).access(a, need);
return std::move(*this);
}
inline virtual mmap& access(Access a, bool need=false) & noexcept
{
switch(a) {
case Access::Random: ::map_advise_rand(const_cast<mmap_t*>(&inner), int(need));
default: break;
}
return *this;
}
inline const span<const unsigned char> as_span() const noexcept { return span(as_ptr(), size()); }
inline span<unsigned char> as_span() noexcept { return span(as_ptr(), size()); }
inline virtual const std::uint8_t* as_ptr() const noexcept { return static_cast<const std::uint8_t*>(inner.ptr); }
inline virtual std::uint8_t* as_ptr() noexcept { return static_cast<std::uint8_t*>(inner.ptr); }
inline virtual std::size_t size() const noexcept { return inner.len; }
inline virtual int as_fd() const { return inner.fd; }
inline virtual const mmap_t& as_raw() const noexcept { return inner; }
protected:
inline mmap(int fd, size_t sz)
: inner(create_raw_fd(fd, sz)) {}
inline explicit mmap(int fd)
: inner(create_raw_fd(fd)) {}
inline virtual mmap_t& as_raw() noexcept { return const_cast<mmap_t&>( inner ); }
private:
const mmap_t inner;
};
//template mmap::map_raw_fd<mmap>(int, size_t); // Probably not needed?
//template mmap::allocate<mmap>(int, size_t);
struct vmap : public mmap {
inline explicit vmap(mmap_t m) noexcept : mmap(m) {}
vmap();
vmap(size_t);
inline explicit vmap(int fd) noexcept : mmap(fd) {}
//vmap(const char* file);
//int as_fd() const override; unneeded
inline virtual ~vmap() { /* unmap_and_close() is called by super */ }
//TODO: Implement this ^ with `memfd_create()`, etc.
};
template<MemMap M, MemMap D = M>
inline D dup_map(const M& map, size_t resize, map_flags flags =0)
{
const mmap& m = static_cast<const mmap&>(map);
mmap_t out;
if(! ::dup_map(&m.as_raw(), &out, &resize, flags)) panic("Failed to duplicate mapping");
return D{out};
}
template<MemMap M, MemMap D = M>
inline D dup_map(const M& map, map_flags flags =0)
{
const mmap& m = static_cast<const mmap&>(map);
mmap_t out;
if(! ::dup_map(&m.as_raw(), &out, nullptr, flags)) panic("Failed to duplicate mapping");
return D{out};
}
#if 0
// dup_map() deduction guids (XXX: Are these needed, or even valid?)
template<MemMap D>
dup_map(const mmap& m, size_t s, map_flags f) -> dup_map<mmap, D>;
template<>
dup_map(const mmap& m, size_t s, map_flags f) -> dup_map<mmap, mmap>;
template<MemMap M>
dup_map(const M& m, size_t s, map_flags f) -> dup_map<M, M>;
template<MemMap D>
dup_map(const mmap& m, map_flags f) -> dup_map<mmap, D>;
template<>
dup_map(const mmap& m, map_flags f) -> dup_map<mmap, mmap>;
template<MemMap M>
dup_map(const M& m, map_flags f) -> dup_map<M, M>;
#endif
}
#undef restrict
#undef MIFCXX
#undef MIFC
#endif
#endif /* _MAP_H */