From 3fa4ac8b89ae722c9816ae56cea150cb55f603a6 Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Fri, 15 May 2020 22:32:14 +0200 Subject: [PATCH] implemented new structures --- include/gp/pointers.hpp | 191 ++++++++++++++++++++++++++++++++++ include/gp/vfs/channel_fs.hpp | 149 ++++++++++++++++++++++++++ 2 files changed, 340 insertions(+) create mode 100644 include/gp/pointers.hpp create mode 100644 include/gp/vfs/channel_fs.hpp diff --git a/include/gp/pointers.hpp b/include/gp/pointers.hpp new file mode 100644 index 0000000..cec766e --- /dev/null +++ b/include/gp/pointers.hpp @@ -0,0 +1,191 @@ +#pragma once +#include "gp/algorithm/move.hpp" +#include "gp/buffer.hpp" +#include "gp/function.hpp" +#include "gp/algorithm/modifiers.hpp" + +template +class unique_ptr; + +template +class unique_ptr { + T* ptr; + gp::function deallocator; +public: + unique_ptr() + : ptr{nullptr} + {} + + template + unique_ptr(T* _ptr, deal func) + : ptr{_ptr} + , deallocator{func} + {} + + unique_ptr(unique_ptr&) = delete; + + unique_ptr(unique_ptr&& oth) + : ptr{oth.ptr} + , deallocator{oth.deallocator} + { + oth.ptr = nullptr; + } + + void operator=(unique_ptr&) = delete; + + void operator=(unique_ptr&& oth) { + ptr = oth.ptr; + deallocator = oth.deallocator; + oth.ptr = nullptr; + } + + operator bool() { + return ptr != nullptr; + } + + T* operator->() { + return ptr; + } + + T* operator*() { + return ptr; + } + + ~unique_ptr() { + if(ptr) { + ptr->~T(); + gp_config::assertion(deallocator(ptr), "freeing unique_ptr failed"); + } + } +}; + +template +class unique_ptr>{ + T* ptr; + gp::reference_wrapper ref; +public: + unique_ptr() + : ptr{nullptr} + {} + + template + unique_ptr(Args ...args, allocator& _ref) + : ref{_ref} { + auto p = ref.get().allocate(sizeof(T)); + if(p) + { + ptr = new(p) T(args...); + } else { + ptr = nullptr; + } + } + + unique_ptr(T* _ptr, allocator& _ref) + : ptr{_ptr} + , ref{_ref} + {} + + unique_ptr(unique_ptr&) = delete; + + unique_ptr(unique_ptr&& oth) + : ptr{oth.ptr} + , ref{oth.ref} + { + oth.ptr = nullptr; + } + + void operator=(unique_ptr&) = delete; + + void operator=(unique_ptr&& oth) { + ptr = oth.ptr; + ref = oth.ref; + oth.ptr = nullptr; + } + + operator bool() { + return ptr != nullptr; + } + + T* operator->() { + return ptr; + } + + T* operator*() { + return ptr; + } + + ~unique_ptr() { + if(ptr) { + ptr->~T(); + gp_config::assertion(ref.get().deallocate(ptr), "freeing unique_ptr failed"); + } + } +}; + +template +class unique_ptr{ + T* ptr; + allocator alloc; +public: + unique_ptr() + : ptr{nullptr} + {} + + unique_ptr(T* _ptr, allocator _alloc = allocator{}) + : ptr{_ptr} + , alloc{_alloc} + {} + + template + unique_ptr(Args ...args, allocator _alloc = allocator{}) + : alloc{_alloc} { + auto p = alloc.allocate(sizeof(T)); + if(p) + { + ptr = new(p) T(args...); + } else { + ptr = nullptr; + } + } + + unique_ptr(unique_ptr&) = delete; + + unique_ptr(unique_ptr&& oth) + : ptr{oth.ptr} + , alloc{oth.alloc} + { + oth.ptr = nullptr; + } + + void operator=(unique_ptr&) = delete; + + void operator=(unique_ptr&& oth) { + ptr = oth.ptr; + alloc = oth.alloc; + oth.ptr = nullptr; + } + + operator bool() { + return ptr != nullptr; + } + + T* operator->() { + return ptr; + } + + T* operator*() { + return ptr; + } + + ~unique_ptr() { + if(ptr) { + ptr->~T(); + gp_config::assertion(alloc.deallocate(ptr), "freeing unique_ptr failed"); + } + } +}; + +class unique_array_ptr { + gp::buffer data; + +}; \ No newline at end of file diff --git a/include/gp/vfs/channel_fs.hpp b/include/gp/vfs/channel_fs.hpp new file mode 100644 index 0000000..7b34768 --- /dev/null +++ b/include/gp/vfs/channel_fs.hpp @@ -0,0 +1,149 @@ +#pragma once +#include "gp/array.hpp" +#include "gp/algorithm/move.hpp" +#include "gp/vfs/fs_types.hpp" +#include "gp/allocator/aggregator.hpp" + +namespace gp { + template + class self_filling_channel{ + error_function on_error; + pop_function filler; + public: + gp::buffer::associated_iterator push(gp::buffer input) { + on_error(); + return input.begin(); + } + gp::buffer::associated_iterator pop(gp::buffer dest) { + return filler(dest); + } + }; + + template + class channel { + gp::array message_sizes; + gp::array< + gp::array, + count + > messages; + size_t r_offset = 0; + size_t w_offset = 0; + [[nodiscard]] size_t write_one(size_t loc, gp::buffer message) { + auto cond = message.size(); + size_t idx = 0; + for(; idx < cond; ++idx) { + messages[loc][idx] = message[idx]; + } + message_sizes[loc] = message.size(); + w_offset += 1; + if constexpr (count != 1) w_offset %= size; + if constexpr (zero_out) { + auto ret = idx; + for(; idx < messages[loc].size(); ++idx) { + messages[loc] = 0; + } + return ret; + } + return idx; + } + [[nodiscard]] size_t read_one(size_t loc, gp::buffer message) { + size_t ret; + size_t idx = 0; + size_t trailer = 0; + if(message_sizes[loc] < message.size()) + { + for(; idx < message_sizes[loc]; ++idx) { + message[idx] = messages[loc][idx]; + } + r_offset += 1; + if constexpr (count != 1) w_offset %= size; + ret = idx; + } else { + for(; idx < message.size(); ++idx) { + message[idx] = messages[loc][idx]; + } + ret = idx; + for(; idx < message_sizes[loc]; ++idx, ++trailer) + { + message[trailer] = message[idx]; + } + message_sizes[loc] = trailer; + } + + if constexpr (zero_out) { + if(trailer == 0) { + message_sizes[loc] = 0; + } + for(; trailer < messages[loc].size(); ++trailer) + { + messages[loc][trailer] = 0; + } + } + + return ret; + } + public: + channel() {} + gp::buffer::associated_iterator push(gp::buffer input) { + if constexpr (whole_messages) { + if(input.size() > size) { + return input.begin(); + } + } + if constexpr (count == 1) { + if(w_offset == r_offset) { + auto to_write = gp::min(input.size(), size); + write_one( + 0, + gp::buffer(input.begin().data, to_write) + ); + return input.begin()+to_write; + } else { + return input.begin(); + } + } else { + auto next_w = (w_offset+1)%count; + auto to_consume = input; + while(to_consume.size() && (next_w == r_offset)) { + auto to_write = gp::min(to_consume.size(), size); + to_write = write_one( + w_offset, + to_consume.trim_start(to_write) + ); + to_consume = to_consume.trim_start(to_write); + next_w = (w_offset+1)%count; + } + return to_consume.begin(); + } + } + gp::buffer::associated_iterator pop(gp::buffer dest) { + if(r_offset == w_offset) { + return dest.begin(); + } + size_t idx; + if constexpr (count == 1) { + idx = 0; + } else { + idx = r_offset; + } + if constexpr (whole_messages) { + if(message_sizes[idx] > dest.size()) { + return dest.begin(); + } + auto sz = gp::min(message_sizes[idx], dest.size()); + read_one(idx, gp::buffer(dest.begin(), sz)); + return dest.begin()+sz; + } + auto to_fill = dest; + do{ + auto to_read = gp::min(to_fill.size(), size); + to_read = read_one( + r_offset, + to_fill.trim_start(to_read) + ); + to_fill = to_fill.trim_start(to_read); + }while(r_offset != w_offset && to_fill.size()); + return to_fill.begin(); + } + }; +} \ No newline at end of file