From 4b7180ed5d14dce381e7b3f7432a243ab059a443 Mon Sep 17 00:00:00 2001 From: Avril Date: Fri, 4 Jun 2021 19:43:58 +0100 Subject: [PATCH] C++ wrapper start --- include/cow.h | 10 +++++++++- include/cow.hpp | 38 ++++++++++++++++++++++++++++++++++++++ src/cow.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 include/cow.hpp create mode 100644 src/cow.cpp diff --git a/include/cow.h b/include/cow.h index 0447d4f..6652cb2 100644 --- a/include/cow.h +++ b/include/cow.h @@ -1,10 +1,14 @@ #ifndef _COW_H #define _COW_H +#ifdef __cplusplus +#define restrict __restrict__ +#endif + #include // Copy-on-write mapped memory. -typedef struct cow cow_t, *cow; +typedef struct cow 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. @@ -29,4 +33,8 @@ size_t cow_size(const cow_t* cow); //XXX: Too unsafe and not useful enough to warrant a function/macro. //#define cow_from_ptr(p) (cow_t*)(&(p)) +#ifdef __cplusplus +#undef restrict +#endif + #endif /* _COW_H */ diff --git a/include/cow.hpp b/include/cow.hpp new file mode 100644 index 0000000..4baa852 --- /dev/null +++ b/include/cow.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "cow.h" + +#include + +struct Cow { + Cow() = delete; + + Cow(size_t size); + Cow(Cow&& m); + virtual ~Cow(); + + static Cow from_raw(cow_t* owned); + + struct Fake; + + private: + struct _inner; + Cow(cow_t* raw); + protected: + const std::shared_ptr<_inner> super; + Cow(const Cow& c); +}; + +struct Cow::Fake : Cow { + Fake() = delete; + + Fake(const Fake& c); + Fake(Fake&& m); + + ~Fake(); + static Fake from_parent(const Cow& parent); + private: + Fake(const Cow& parent); + cow_t* fake; +}; + diff --git a/src/cow.cpp b/src/cow.cpp new file mode 100644 index 0000000..212265d --- /dev/null +++ b/src/cow.cpp @@ -0,0 +1,39 @@ +#include + +#include + +struct Cow::_inner { + cow_t* ptr; + + ~_inner(); + _inner(size_t sz); + _inner(cow_t* ptr); + + _inner(const _inner& copy) = delete; + _inner(_inner&& move) = delete; + _inner() = delete; +}; +Cow::_inner::~_inner() { + if(ptr) { + cow_free(ptr); + ptr = nullptr; + } +} +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)){} +Cow::~Cow(){} +Cow::Cow(Cow&& m) : super(std::move(*const_cast*>(&super))){} + +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::Fake(const Cow& parent) : Cow(parent), fake(cow_clone(parent.super->ptr)){} +Cow::Fake::~Fake() { if(fake) { cow_free(fake); *const_cast(&fake) = nullptr; } } +Cow::Fake Cow::Fake::from_parent(const Cow& parent) { return Fake(parent); } + +Cow::Fake::Fake(Fake&& move) : Cow(std::move(move)), fake(move.fake) +{ + *const_cast(&fake) = nullptr; +}