diff --git a/Makefile b/Makefile index befc071..f1a1acb 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CXX= clang++-10 CXXFLAGS= --std=c++20 -O0 -g -pthread -DGP_TESTS -DFUZZ_STRENGTH=500 -DNO_BENCH=0 -pedantic \ - -frtti -fprofile-instr-generate -fcoverage-mapping -Wno-unknown-attributes \ + -fprofile-instr-generate -fcoverage-mapping -Wno-unknown-attributes \ -fsanitize=address -fno-omit-frame-pointer all: tests diff --git a/include/gp/algorithm/move.hpp b/include/gp/algorithm/move.hpp index b3fc98b..dff2baa 100644 --- a/include/gp/algorithm/move.hpp +++ b/include/gp/algorithm/move.hpp @@ -28,9 +28,31 @@ namespace gp{ T& rhs ) { - auto tmp = lhs; - lhs = rhs; - rhs = tmp; + auto tmp = gp::move(lhs); + lhs = gp::move(rhs); + rhs = gp::move(tmp); + } + + template + constexpr void swap( + T&& lhs, + T& rhs + ) + { + auto tmp = gp::move(lhs); + lhs = gp::move(rhs); + rhs = gp::move(tmp); + } + + template + constexpr void swap( + T& lhs, + T&& rhs + ) + { + auto tmp = gp::move(lhs); + lhs = gp::move(rhs); + rhs = gp::move(tmp); } template diff --git a/include/gp/enveloppe/cbor.hpp b/include/gp/enveloppe/cbor.hpp index 0f511da..cc2f425 100644 --- a/include/gp/enveloppe/cbor.hpp +++ b/include/gp/enveloppe/cbor.hpp @@ -76,13 +76,13 @@ namespace gp { template using cbor_composite = gp::fixed_variant< cbor_number, - gp::buffer, - bool, - gp::vector, + //gp::buffer, + //bool, + //gp::vector, gp::vector>, - gp::nullopt_t, - undefined_t, - cbor_floating_point + //gp::nullopt_t, + undefined_t//, + //cbor_floating_point >; class cbor_value { @@ -101,6 +101,16 @@ namespace gp { , alloc(alloc_v) {} + cbor_value(cbor_value& oth) + : contents(oth.contents) + , alloc(oth.alloc) + {} + + cbor_value(cbor_value&& oth) + : contents(gp::move(oth.contents)) + , alloc(gp::move(oth.alloc)) + {} + cbor_value& operator=(cbor_value& value) { contents = value.contents; alloc = value.alloc; diff --git a/include/gp/function.hpp b/include/gp/function.hpp index e60e6a6..401289c 100644 --- a/include/gp/function.hpp +++ b/include/gp/function.hpp @@ -74,43 +74,34 @@ namespace gp{ , condestructor(reinterpret_cast(condestruct)) , data_ptr( sizeof(func) <= sizeof(data_ptr) - ? 0 + ? nullptr : details::ensure( [&](){return alloc.has_value();}, [&](){return (char*)(alloc.value().get().allocate(sizeof(func)));} ) ) , data_size( - sizeof(func) <= sizeof(data_ptr) - ? 0 - : sizeof(func) + sizeof(func) ) { - gp_config::assertion(!(alloc.has_value() && data_ptr == nullptr), "allocator failed in function"); - if(data_ptr != nullptr) this->condestructor(data_size < sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, reinterpret_cast(&f)); + gp_config::assertion(data_size <= sizeof(func) || !(alloc.has_value() && data_ptr == nullptr), "allocator failed in function"); + this->condestructor(data_size <= sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, reinterpret_cast(&f)); } template - function(func f, nullopt_t alloc_v = nullopt) + function(func f, nullopt_t alloc_v) : alloc(alloc_v) , invokator(reinterpret_cast(invoke)) , condestructor(reinterpret_cast(condestruct)) - , data_ptr( - sizeof(func) <= sizeof(data_ptr) - ? 0 - : details::ensure( - [&](){return alloc.has_value();}, - [&](){return (char*)(alloc.value().get().allocate(sizeof(func)));} - ) - ) + , data_ptr() , data_size( - sizeof(func) <= sizeof(data_ptr) - ? 0 - : sizeof(func) + details::ensure( + [&](){return sizeof(func) <= sizeof(data_ptr);}, + [&](){return sizeof(func);} + ) ) { - gp_config::assertion(!(alloc.has_value() && data_ptr == nullptr), "allocator failed in function"); - if(data_ptr != nullptr) this->condestructor(data_size < sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, reinterpret_cast(&f)); + this->condestructor((char*)&data_ptr, reinterpret_cast(&f)); } function(function const& rhs) @@ -127,25 +118,29 @@ namespace gp{ ) , data_size(rhs.data_size) { - gp_config::assertion(!(alloc.has_value() && data_ptr == nullptr), "allocator failed in function"); + gp_config::assertion(data_size <= sizeof(data_ptr) || !(alloc.has_value() && data_ptr == nullptr), "allocator failed in function"); if( - data_ptr != nullptr - and rhs.data_ptr != nullptr - ) this->condestructor(data_size <= sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, rhs.data_ptr); + data_size != 0 + and rhs.data_size != 0 + ) this->condestructor( + data_size <= sizeof(data_ptr) ? (char*)&data_ptr : data_ptr, + data_size <= sizeof(data_ptr) ? (char*)&(rhs.data_ptr) : rhs.data_ptr + ); } function(function&& rhs) : alloc(rhs.alloc) , invokator(rhs.invokator) , condestructor(rhs.condestructor) - , data_ptr(data_size <= sizeof(data_ptr) ? 0 : rhs.data_ptr) + , data_ptr(rhs.data_size <= sizeof(data_ptr) ? nullptr : rhs.data_ptr) , data_size(rhs.data_size) { - if(data_size <= sizeof(data_ptr) && data_size != 0 && data_ptr != nullptr && alloc.has_value()) { + if(data_size != 0 && data_size <= sizeof(data_ptr)) { condestructor((char*)&data_ptr, (char*)&rhs.data_ptr); condestructor(nullptr, (char*)&rhs.data_ptr); } rhs.data_ptr = nullptr; + rhs.data_size = 0; } ~function(){ @@ -179,7 +174,7 @@ namespace gp{ alloc = rhs.alloc; invokator = rhs.invokator; condestructor = rhs.condestructor; - condestructor(nullptr, data_ptr); + if(data_size) condestructor(nullptr, data_ptr); alloc.value().get().deallocate(data_ptr); data_ptr = rhs.data_size <= sizeof(data_ptr) ? 0 @@ -198,7 +193,11 @@ namespace gp{ } ret operator()(args&&... argv) { - return invokator(data_ptr, gp::forward(argv)...); + return invokator(data_size <= sizeof(data_ptr) ? (fn_ptr)&data_ptr : data_ptr, gp::forward(argv)...); + } + + bool ready() { + return invokator != nullptr; } }; diff --git a/include/gp/optional.hpp b/include/gp/optional.hpp index 7044bda..38d7ec9 100644 --- a/include/gp/optional.hpp +++ b/include/gp/optional.hpp @@ -39,6 +39,12 @@ namespace gp{ new(buffer) T(gp::move(value)); } + ~optional() { + if(ready) { + ((T*)buffer)->~T(); + } + } + optional& operator=(nullopt_t) { if(ready) { ((T*)buffer)->~T(); diff --git a/include/gp/variant.hpp b/include/gp/variant.hpp index 51a3b0a..3d8609c 100644 --- a/include/gp/variant.hpp +++ b/include/gp/variant.hpp @@ -2,6 +2,7 @@ #include "gp_config.hpp" +#include #include #include "gp/allocator/dummy.hpp" #include "gp/exception.hpp" @@ -18,19 +19,26 @@ namespace gp{ class fixed_variant final { std::size_t index = std::numeric_limits::max(); char buffer[max_size()]; - gp::function cpytor = [](void*, void*){}; - gp::function mvtor = [](void*, void*){}; - gp::function dtor = [](void*){}; + gp::function cpytor = {[](void*, void*){}, nullopt}; + gp::function mvtor = {[](void*, void*){}, nullopt}; + gp::function dtor = {[](void*){}, nullopt}; static_assert(all_of_fixed_size::value, "not fixed"); + + void buffswap(fixed_variant& oth) { + char tmp[max_size()]; + mvtor(tmp, buffer); + oth.mvtor(buffer, oth.buffer); + mvtor(oth.buffer, tmp); + } public: template//, typename std::enable_if::value,int>::type> constexpr fixed_variant(U& value) : index{r_index_of::value} { new(buffer) U(value); - dtor = gp::function([](void* thing){((U*)thing)->~U();}); - cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}); - mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}); + dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt); + cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt); + mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt); } template//, typename std::enable_if::value,int>::type> @@ -38,9 +46,9 @@ namespace gp{ : index{r_index_of::value} { new(buffer) U(std::move(value)); - dtor = gp::function([](void* thing){((U*)thing)->~U();}); - cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}); - mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}); + dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt); + cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt); + mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt); } constexpr fixed_variant(fixed_variant& oth) @@ -52,6 +60,15 @@ namespace gp{ cpytor(oth.buffer, buffer); } + constexpr fixed_variant(fixed_variant&& oth) + { + mvtor(buffer, oth.buffer); + gp::swap(dtor, oth.dtor); + gp::swap(cpytor, oth.cpytor); + gp::swap(mvtor, oth.mvtor); + gp::swap(index, oth.index); + } + template constexpr size_t alt() const { return r_index_of::value; @@ -70,7 +87,17 @@ namespace gp{ index = value.index; cpytor = value.cpytor; dtor = value.dtor; - mvtor(value.buffer, buffer); + mvtor = value.mvtor; + cpytor(value.buffer, buffer); + } + + void operator=(fixed_variant&& value) + { + buffswap(value); + gp::swap(dtor, value.dtor); + gp::swap(cpytor, value.cpytor); + gp::swap(mvtor, value.mvtor); + gp::swap(index, value.index); } template::value,int>::type> @@ -82,9 +109,9 @@ namespace gp{ } index = r_index_of::value; new(buffer) U(value); - dtor = gp::function([](void* thing){((U*)thing)->~U();}); - cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}); - mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}); + dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt); + cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt); + mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt); } template::value,int>::type> @@ -95,17 +122,18 @@ namespace gp{ dtor((void*)buffer); } index = r_index_of::value; - new(buffer) U(std::move(value)); - dtor = gp::function([](void* thing){((U*)thing)->~U();}); - cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}); - mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}); + dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt); + cpytor = gp::function([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt); + mvtor = gp::function([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt); + mvtor(buffer, value.buffer); } ~fixed_variant() { - if(index != std::numeric_limits::max()) + if(index != std::numeric_limits::max() && dtor.ready()) { dtor((void*)buffer); + index = std::numeric_limits::max(); } } diff --git a/include/gp/vector.hpp b/include/gp/vector.hpp index 02e2c34..c404f6c 100644 --- a/include/gp/vector.hpp +++ b/include/gp/vector.hpp @@ -8,9 +8,9 @@ namespace gp{ template class vector final { - T* ary; - size_t sz; - size_t cap; + T* ary = nullptr; + size_t sz = 0; + size_t cap = 0; gp::reference_wrapper alloc; public: using associated_iterator = pointer_iterator; @@ -69,7 +69,7 @@ namespace gp{ gp_config::assertion(reserve(oth.size()), "could not reserve space on assign"); for(size_t i = 0; i < gp::min(sz, oth.sz); ++i) { - ary[i]=oth[i]; + new(ary+i) T(oth[i]); } if(sz < oth.sz) { for(size_t i = sz; i < oth.sz; ++i) { @@ -131,10 +131,10 @@ namespace gp{ if(T* new_ary = (T*)alloc.get().allocate(new_data_size); new_ary) { auto new_it = new_ary; for(auto& elem : *this) { - *(++new_it) = gp::move(elem); + new(++new_it) T(gp::move(elem)); } - gp_config::assertion(alloc.get().deallocate(ary), "failed to deallocate old range"); + if(ary != nullptr) gp_config::assertion(alloc.get().deallocate(ary), "failed to deallocate old range"); ary = new_ary; cap = new_cap; diff --git a/tests.cpp b/tests.cpp index eac275a..9c79511 100644 --- a/tests.cpp +++ b/tests.cpp @@ -23,13 +23,13 @@ int main() { ++runned; int value; - /*try{*/ + try{ value = test->run(); if(value) { std::cout << std::dec << test->name << " failed with "<< value << std::endl; } - /*} catch (gp::runtime_error err) { + } catch (gp::runtime_error err) { std::cout << test->name << " failed with an exception: " << err.what() << std::endl; value = -1; } catch (gp_config::assert_failure err) { @@ -38,7 +38,7 @@ int main() } catch (...) { std::cout << test->name << " failed with an exception" << std::endl; value = -1; - }*/ + } failed += (value != 0); } std::cout << std::dec << "Runned "<* buff = new gp::array(); + auto buff = std::make_unique>(); auto begin = std::chrono::steady_clock::now(); @@ -141,11 +141,7 @@ struct render_test : public test_scaffold { auto myfile = std::fstream("render.bmp", std::ios::out | std::ios::binary); - myfile.write(buff->begin().data, r_end - buff->begin()); - - myfile.close(); - - delete buff; + myfile.write(buff->begin().data, r_end - buff->begin()); //gp_config::assertion(a.render(vec2{64,32}).x == color_t{1.0,0,0,1.0}.x, "red sphere not perceived"); //gp_config::assertion(a.render(vec2{0,0}).x == color_t{0.0,0,1.0,1.0}.x, "blue sky not perceived");