Compare commits
24 Commits
Author | SHA1 | Date |
---|---|---|
Avril | 130f21f57e | 1 year ago |
Avril | 671fcd3968 | 1 year ago |
Avril | 0d082f5b6f | 1 year ago |
Avril | 6f21491298 | 3 years ago |
Avril | 2d4ebc3142 | 3 years ago |
Avril | 7b623e0fdf | 3 years ago |
Avril | 7e4e3f9867 | 3 years ago |
Avril | 646482c555 | 3 years ago |
Avril | 2c88d329b9 | 3 years ago |
Avril | 382efd5d43 | 3 years ago |
Avril | ffe01128c4 | 3 years ago |
Avril | 30a0176604 | 3 years ago |
Avril | 960f18a6e0 | 3 years ago |
Avril | 8f8d738e0e | 3 years ago |
Avril | a293133f29 | 3 years ago |
Avril | a5d5d1b9fd | 3 years ago |
Avril | aeb3f528d4 | 3 years ago |
Avril | 8d5e587333 | 3 years ago |
Avril | fcd0597dc8 | 3 years ago |
Avril | 1672250ed6 | 3 years ago |
Avril | 8334792d8c | 3 years ago |
Avril | ee1b9af2b9 | 3 years ago |
Avril | 79517ad97a | 3 years ago |
Avril | a834612e23 | 3 years ago |
@ -1,6 +1,8 @@
|
||||
cow-*
|
||||
*.a
|
||||
*.so
|
||||
*.so*
|
||||
obj/
|
||||
*~
|
||||
vgcore.*
|
||||
target/
|
||||
!cowslice/*.a
|
||||
|
@ -0,0 +1,121 @@
|
||||
#pragma once
|
||||
|
||||
#include <cow.hpp>
|
||||
#include <utility>
|
||||
|
||||
template<typename T>
|
||||
struct TypedCow : public _cow_util::Span<T> {
|
||||
struct Fake;
|
||||
|
||||
template<typename... Args>
|
||||
inline TypedCow(size_t sz, Args&&... args) : real(Cow(sz * sizeof(T))) { init_copy( T(std::forward<Args>(args)...) ); }
|
||||
inline TypedCow(size_t sz, const T& copy) : real(Cow(sz * sizeof(T))) { init_copy(copy); }
|
||||
inline TypedCow(size_t sz) : TypedCow(sz, T()){}
|
||||
|
||||
inline virtual ~TypedCow() { uninit(); }
|
||||
|
||||
inline virtual Fake clone() const { return Fake(*this); }
|
||||
|
||||
inline virtual cow_t* raw() const { return real.raw(); }
|
||||
|
||||
inline size_t size() const { return real.size() / sizeof(T); }
|
||||
protected:
|
||||
//inline explicit TypedCow(const TypedCow<T>& unsafeCopy) : real(Cow(unsafeCopy.real)){}
|
||||
|
||||
inline virtual void* area() override { return reinterpret_cast<void*>( real.ptr() ); }
|
||||
inline virtual const void* area() const override { return reinterpret_cast<const void*>( real.ptr() ); }
|
||||
|
||||
inline void init_copy(const T& copy_from) {
|
||||
T* ptr = this->ptr();
|
||||
for(size_t i=0;i<size();i++)
|
||||
new ((void*)(ptr+i)) T(copy_from);
|
||||
|
||||
}
|
||||
// UNSAFE: Explicitly calls destructors of each element in this instance.
|
||||
inline void uninit() {
|
||||
T* ptr = this->ptr();
|
||||
if(!ptr) return;
|
||||
|
||||
for(size_t i=0;i<size();i++)
|
||||
(ptr+i)->~T();
|
||||
}
|
||||
private:
|
||||
Cow real;
|
||||
};
|
||||
template<typename T>
|
||||
struct TypedCow<T>::Fake : public TypedCow<T> {
|
||||
//XXX: How THE FUCK do we initialise base's `real` here?????
|
||||
Fake() = delete;
|
||||
|
||||
inline Fake(const Fake& copy) : fake(cow_clone(copy.fake)){}
|
||||
inline Fake(Fake&& move) : fake(move.fake) { *const_cast<cow_t**>(&move.fake) = nullptr; }
|
||||
inline Fake(const TypedCow<T>& clone) : fake(cow_clone(clone.raw())){}
|
||||
|
||||
inline cow_t* raw() const override { return fake; }
|
||||
inline Fake clone() const override { return Fake(*this); }
|
||||
|
||||
inline ~Fake(){}
|
||||
|
||||
inline size_t size() const override { return fake ? cow_size(fake) : 0; }
|
||||
protected:
|
||||
inline void* area() override { return fake ? cow_ptr(fake) : nullptr; }
|
||||
inline const void* area() const override { return fake ? cow_ptr_of(const void, fake) : nullptr; }
|
||||
|
||||
private:
|
||||
cow_t* const fake;
|
||||
};
|
||||
#if 0
|
||||
struct Fake;
|
||||
friend class Fake;
|
||||
|
||||
TypedCow() = delete;
|
||||
inline TypedCow(TypedCow<T>&& move) : Cow(std::move(move.super)) { /* Moves the shared_ptr. No need to move the elements. */ }
|
||||
// protected: copy
|
||||
|
||||
inline TypedCow(size_t sz) : Cow(sz * sizeof(T)) { init_copy(T()); }
|
||||
inline TypedCow(size_t sz, const T& copy_from) : TypedCow(sz) { init_copy(copy_from); }
|
||||
//template<typename... Args>
|
||||
//inline TypedCow(size_t sz, Args&&... args) : TypedCow(sz) { init_copy( T(std::forward<Args>(args)...) ); }
|
||||
|
||||
virtual inline ~TypedCow() { uninit(); }
|
||||
|
||||
inline Cow::Fake clone() const override { return Cow::clone(); }
|
||||
inline Fake clone() const { return Fake(Cow::clone()); }
|
||||
|
||||
inline size_t size() const override { return Cow::size() / sizeof(T); }
|
||||
|
||||
protected:
|
||||
inline void* area() override { return Cow::area(); }
|
||||
inline const void* area() const override { return Cow::area(); }
|
||||
//// Should only be used for creating Fakes. Copies the refcounted pointer.
|
||||
//inline TypedCow(const TypedCow<T>& copy) : Cow(copy.super) {}
|
||||
|
||||
// UNSAFE: Placement-new's copys of `copy_from` into `0..size()` of this instance.
|
||||
inline void init_copy(const T& copy_from) {
|
||||
T* ptr = _cow_util::Span<T>::ptr();
|
||||
for(size_t i=0;i<size();i++)
|
||||
new ((void*)(ptr+i)) T(copy_from);
|
||||
|
||||
}
|
||||
// UNSAFE: Explicitly calls destructors of each element in this instance.
|
||||
inline void uninit() {
|
||||
T* ptr = _cow_util::Span<T>::ptr();
|
||||
for(size_t i=0;i<size();i++)
|
||||
(ptr+i)->~T();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct TypedCow<T>::Fake : private Cow::Fake, public _cow_util::Span<T> {
|
||||
Fake() = delete;
|
||||
explicit inline Fake(Cow::Fake&& untyped) : Cow::Fake(untyped){}
|
||||
inline Fake(const Fake& copy) : Fake(copy.Cow::Fake::clone()){}
|
||||
inline Fake(Fake&& move) : Cow::Fake(std::move(move)) {}
|
||||
inline ~Fake(){}
|
||||
|
||||
inline size_t size() const override { return Cow::Fake::size(); }
|
||||
protected:
|
||||
inline const void* area() const override { return Cow::Fake::area(); }
|
||||
inline void* area() override { return Cow::Fake::area(); }
|
||||
};
|
||||
#endif
|
@ -0,0 +1,3 @@
|
||||
#include "error.h"
|
||||
|
||||
_Thread_local internal enum cow_err_kind _cow_last_error = COW_ERR_NONE;
|
@ -0,0 +1,47 @@
|
||||
#include <array>
|
||||
|
||||
#include <cow.h>
|
||||
|
||||
#include "error.h"
|
||||
|
||||
namespace _cow_error {
|
||||
constexpr const size_t SIZE = (size_t)_COW_ERR_SIZE;
|
||||
|
||||
consteval inline void setmsg(std::array<const char*, SIZE>& ar, enum cow_err_kind kind, const char* msg)
|
||||
{
|
||||
ar[kind] = msg;
|
||||
}
|
||||
|
||||
consteval inline std::array<const char*, SIZE> gen_msg_table()
|
||||
{
|
||||
std::array<const char*, SIZE> ret;
|
||||
|
||||
setmsg(ret, COW_ERR_UNKNOWN, "unknown error");
|
||||
setmsg(ret, COW_ERR_NONE, "success");
|
||||
setmsg(ret, COW_ERR_FDCREATE, "failed to create shmfd (memfd_create())");
|
||||
setmsg(ret, COW_ERR_SIZE, "failed to set shmfd size (ftruncate())");
|
||||
setmsg(ret, COW_ERR_MAP, "failed to map shmfd (mmap())");
|
||||
setmsg(ret, COW_ERR_POISONED, "trying to use a poisoned cow");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::array<const char*, SIZE> _cow_message_table = gen_msg_table();
|
||||
}
|
||||
using namespace _cow_error;
|
||||
|
||||
extern "C" {
|
||||
|
||||
enum cow_err_kind cow_err() {
|
||||
return _cow_last_error;
|
||||
}
|
||||
internal void _cow_set_err(enum cow_err_kind kind) {
|
||||
_cow_last_error = kind;
|
||||
}
|
||||
const char* const * cow_err_msg(enum cow_err_kind kind)
|
||||
{
|
||||
auto idx = ((size_t)kind);
|
||||
if ( idx >= SIZE ) return nullptr;
|
||||
else return &_cow_message_table[idx];
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#ifndef _COW_ERROR_H
|
||||
#define _COW_ERROR_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <cow.h>
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#define _Thread_local thread_local
|
||||
#define restrict __restrict__
|
||||
#endif
|
||||
|
||||
void _cow_set_err(enum cow_err_kind kind) internal;
|
||||
extern _Thread_local internal enum cow_err_kind _cow_last_error;
|
||||
|
||||
#define SOFT_ASSERT(ex, kind, ret) do { if(!(ex)) { return (_cow_last_error = (kind), (ret)); } } while(0)
|
||||
#define SOFT_LASSERT(ex, kind, ret) SOFT_ASSERT(LIKELY(ex), kind, ret)
|
||||
#define SOFT_UASSERT(ex, kind, ret) SOFT_ASSERT(UNLIKELY(ex), kind, ret)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#undef restrict
|
||||
#undef _Thread_local
|
||||
#endif
|
||||
|
||||
#endif /* _COW_ERROR_H */
|
@ -0,0 +1,26 @@
|
||||
|
||||
#ifndef internal
|
||||
#define internal __attribute__((visibility("internal")))
|
||||
#endif /* internal */
|
||||
|
||||
#define LIKELY(ex) __builtin_expect(!!(ex), 1)
|
||||
#define UNLIKELY(ex) __builtin_expect(!!(ex), 0)
|
||||
|
||||
#define box(t) aligned_alloc(_Alignof(t), sizeof(t))
|
||||
|
||||
#if defined(DEBUG) || defined(COW_TRACE)
|
||||
#define TRACE(msg, ...) (fprintf(stderr, "<libcow> [TRACE] %s->%s():%d: " msg "\n", __FILE__, __func__, __LINE__, __VA_ARGS__), (void)0)
|
||||
#else
|
||||
#define TRACE(msg, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if !defined(COW_NO_ASSERT)
|
||||
#define ASSERT(expr, msg) do { if(!(expr)) die("assertion failed: `" #expr "`: " msg); } while(0)
|
||||
#else
|
||||
#define ASSERT(op, msg) ((void)0)
|
||||
#endif
|
||||
|
||||
#define LASSERT(expr, msg) ASSERT(LIKELY(expr), "(unexpected) " msg)
|
||||
#define UASSERT(expr, msg) ASSERT(UNLIKELY(expr), "(expected) " msg)
|
||||
|
||||
|
Loading…
Reference in new issue