removed indirection layer in Cow origin by replacing _inner.ptr with a concrete cow_t _inner.cow

cpp
Avril 3 years ago
parent a9ba264f4b
commit b8699c78db
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -3,7 +3,7 @@ Automatic copy-on-write semantic memory slices for use in C (and C++)
# Usage
See `include/cow.h` for documentation on each function.
Each function, macro, and type definition in the header will be prefixed with `cow_` or `COW_`.
Each function, macro, and type definition in the header will be prefixed with `cow_` or `COW_`. Internal non-prototpyed items use the namespace `_cow_` or `_COW_`.
## Building
Run `make` to build to build the `release` (optimised) target of the library.

@ -9,7 +9,7 @@ extern "C" {
#include <stdlib.h>
// Copy-on-write mapped memory.
typedef struct cow cow_t;
typedef struct cow_mapped_slice cow_t;
/// Create a new copy-on-write area of `size` bytes.
/// Writes to this instance pointer (`cow_ptr()`) are written to the allocated memory.

@ -31,14 +31,8 @@
#define LASSERT(expr, msg) ASSERT(LIKELY(expr), "(unexpected) " msg)
#define UASSERT(expr, msg) ASSERT(UNLIKELY(expr), "(expected) " msg)
struct cow {
void* origin; // ptr to mapped memory. This *MUST* be the first field and have an offset of 0.
int fd; // Will be ORd with ~INT_MAX if it's a clone. Will be >0 if it's the original.
size_t size;
}; // cow_t, *cow
_Static_assert(offsetof(cow_t, origin) == 0, "`cow_t.origin` must have an offset of 0.");
// struct cow { ... }
#include "cow_t.h"
static __attribute__((noreturn)) __attribute__((noinline)) __attribute__((cold)) void die(const char* error)
{
@ -92,7 +86,7 @@ size_t cow_size(const cow_t* cow)
return cow->size;
}
cow_t* cow_create(size_t size)
inline internal cow_t _cow_create_unboxed(size_t size)
{
cow_t ret;
ret.size = size;
@ -101,15 +95,24 @@ cow_t* cow_create(size_t size)
if(ret.origin == MAP_FAILED) die("cow_create:mmap");
TRACE("mapped new origin cow page of %lu size at %p (memfd %d)", size, ret.origin, ret.fd);
return box_value(ret);
return ret;
}
cow_t* cow_create(size_t size)
{
return box_value(_cow_create_unboxed(size));
}
void cow_free(cow_t* restrict cow)
inline internal void _cow_free_unboxed(const cow_t* cow)
{
TRACE("unmapping %s cow of %lu size from %p (fd %d, real fd %d)", cow_is_fake(cow) ? "fake" : "and closing fd of origin", cow->size, cow->origin, cow->fd, cow_real_fd(cow));
munmap(cow->origin, cow->size);
if(!cow_is_fake(cow))
close(cow->fd);
}
void cow_free(cow_t* restrict cow)
{
_cow_free_unboxed(cow);
free(cow);
}

@ -2,8 +2,13 @@
#include <utility>
#include "cow_t.h"
struct Cow::_inner {
cow_t* ptr;
cow_t cow;
inline const cow_t* ptr() const { return &cow; }
inline cow_t* ptr() { return &cow; }
~_inner();
_inner(size_t sz);
@ -14,13 +19,13 @@ struct Cow::_inner {
_inner() = delete;
};
Cow::_inner::~_inner() {
if(ptr) {
cow_free(ptr);
ptr = nullptr;
_cow_free_unboxed(ptr());
}
Cow::_inner::_inner(size_t sz) : cow(_cow_create_unboxed(sz)){}
Cow::_inner::_inner(cow_t* ptr) : cow(*ptr)
{
free(ptr);
}
Cow::_inner::_inner(size_t sz) : ptr(cow_create(sz)){}
Cow::_inner::_inner(cow_t* ptr) : ptr(ptr){}
Cow::Cow(size_t size) : super(std::make_shared<_inner>(size)){}
Cow::Cow(cow_t* raw) : super(std::make_shared<_inner>(raw)){}
@ -32,9 +37,9 @@ Cow::~Cow(){}
Cow Cow::from_raw(cow_t* owned) { if(cow_is_fake(owned)) throw "Trying to create real from fake raw"; else return Cow(owned); }
Cow::Fake Cow::clone() const { return Fake::from_real(*this); }
cow_t* Cow::get_raw() const { return super->ptr; }
cow_t* Cow::get_raw() const { return super->ptr(); }
Cow::Fake::Fake(const Cow& copy) : Cow(copy), fake(cow_clone(copy.super->ptr)){}
Cow::Fake::Fake(const Cow& copy) : Cow(copy), fake(cow_clone(copy.super->ptr())){}
Cow::Fake::Fake(const Fake& copy) : Cow(copy), fake(cow_clone(copy.fake)){}//Fake(*static_cast<const Cow*>(&copy)){}
Cow::Fake::Fake(Fake&& move) : Cow(std::move(move)), fake(move.fake)
{

@ -0,0 +1,38 @@
// Internal header for defining the `cow_t` concrete type to be used with the C and C++ APIs.
#ifndef _COW_T_H
#define _COW_T_H
#define internal __attribute__((visibility("internal")))
#ifdef __cplusplus
#define restrict __restrict__
extern "C" {
#endif
#include <stdlib.h>
#include <cow.h>
struct cow_mapped_slice {
void* origin; // ptr to mapped memory. This *MUST* be the first field and have an offset of 0.
int fd; // Will be ORd with ~INT_MAX if it's a clone. Will be >0 if it's the original.
size_t size;
}; // cow_t, *cow
#ifdef __cplusplus
static_assert
#else
_Static_assert
#endif
(offsetof(cow_t, origin) == 0, "`cow_t.origin` must have an offset of 0.");
cow_t _cow_create_unboxed(size_t size) internal;
void _cow_free_unboxed(const cow_t* cow) internal;
#ifdef __cplusplus
}
#undef restruct
#endif
#endif /* _COW_T_H */
Loading…
Cancel
Save