diff --git a/src/lib/test/tracking-allocator.cpp b/src/lib/test/tracking-allocator.cpp new file mode 100644 index 000000000..bcc3acc7d --- /dev/null +++ b/src/lib/test/tracking-allocator.cpp @@ -0,0 +1,120 @@ +/* + TrackingAllocator - test dummy objects for tracking ctor/dtor calls + + Copyright (C) Lumiera.org + 2024, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +/** @file tracking-allocator.cpp + ** Implementation of the common storage backend for the tracking test allocator. + ** + ** @see tracking-allocator.hpp + ** @see TestTracking_test#demonstrate_checkAllocator() + ** + */ + + +//#include "lib/test/test-helper.hpp" +#include "lib/test/tracking-allocator.hpp" +//#include "lib/format-string.hpp" +//#include "lib/format-cout.hpp" +//#include "lib/unique-malloc-owner.hpp" +#include "lib/depend.hpp" +#include "lib/uninitialised-storage.hpp" + + +//#include + +//using util::_Fmt; +//using std::string; + +namespace lib { +namespace test{ + + namespace { // implementation details for common memory management + + struct Allocation + { + UninitialisedDynBlock buff; + }; + + /** + * @internal registration and tracking of memory allocations handed out. + */ + class MemoryPool + { + + }; + + Depend globalPool; + } + + + TrackingAllocator::TrackingAllocator() + : mem_{} + { } + + TrackingAllocator::TrackingAllocator (Literal id) + : mem_{} + { + UNIMPLEMENTED ("attach to specific pool"); + } + + + void* + TrackingAllocator::allocate (size_t n) + { + UNIMPLEMENTED ("allocate memory block of size n"); + } + + void + TrackingAllocator::deallocate (void* loc) noexcept + { + UNIMPLEMENTED ("allocate memory block of size n"); + } + + + + /* ===== Diagnostics ===== */ + + EventLog TrackingAllocator::log{"test::TrackingAllocator"}; + + + HashVal + TrackingAllocator::checksum (Literal pool) + { + UNIMPLEMENTED ("get Checksum for mem-pool"); + } + + size_t + TrackingAllocator::numAlloc (Literal pool) + { + UNIMPLEMENTED ("get allocation count for mem-pool"); + } + + size_t + TrackingAllocator::numBytes (Literal pool) + { + UNIMPLEMENTED ("calc allotted Bytes for mem-pool"); + } + + + + +}} // namespace lib::test diff --git a/src/lib/test/tracking-allocator.hpp b/src/lib/test/tracking-allocator.hpp index af016784b..7a8484884 100644 --- a/src/lib/test/tracking-allocator.hpp +++ b/src/lib/test/tracking-allocator.hpp @@ -32,151 +32,114 @@ #define LIB_TEST_TRACKING_ALLOCATOR_H #include "lib/error.hpp" +#include "lib/nocopy.hpp" +#include "lib/hash-value.h" +#include "lib/symbol.hpp" +#include "lib/test/event-log.hpp" -#include +//#include #include +#include #include +using std::byte; namespace lib { - namespace allo {///< Concepts and Adaptors for custom memory management +namespace test { + - /////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1366 : define Allocator Concepts here - /// TODO the following Concepts can be expected here (with C++20) - /// - Allocator : for the bare memory allocation - /// - Factory : for object fabrication and disposal - /// - Handle : a functor front-end to be dependency-injected + namespace { // common memory management for the TrackingAllocator + const Symbol GLOBAL{"GLOBAL"}; - /** - * Adapter to implement the *Factory* concept based on a `std::allocator` - * @tparam ALO a std::allocator instance or anything compliant to [Allocator] - * [Allocator]: https://en.cppreference.com/w/cpp/named_req/Allocator - * @note in addition to the abilities defined by the standard, this adapter - * strives to provide some kind of _lateral leeway,_ attempting to - * create dedicated allocators for other types than the BaseType - * implied by the given \a ALO (standard-allocator). - * - this is possible if the rebound allocator can be constructed - * from the given base allocator - * - alternatively, an attempt will be made to default-construct - * the rebound allocator for the other type requested. - * @warning Both avenues for adaptation may fail, - * which could lead to compilation or runtime failure. - * @remark deliberately this class inherits from the allocator, - * allowing to exploit empty-base-optimisation, since - * usage of monostate allocators is quite common. - */ - template - class StdFactory - : private ALO - { - using Allo = ALO; - using AlloT = std::allocator_traits; - using BaseType = typename Allo::value_type; - - Allo& baseAllocator() { return *this; } - - template - auto - adaptAllocator() - { - using XAllo = typename AlloT::template rebind_alloc; - if constexpr (std::is_constructible_v) - return XAllo{baseAllocator()}; - else - return XAllo{}; - } - - template - typename ALOT::pointer - construct (typename ALOT::allocator_type& allo, ARGS&& ...args) - { - auto loc = ALOT::allocate (allo, 1); - try { ALOT::construct (allo, loc, std::forward(args)...); } - catch(...) - { - ALOT::deallocate (allo, loc, 1); - throw; - } - return loc; - } - - template - void - destroy (typename ALOT::allocator_type& allo, typename ALOT::pointer elm) - { - ALOT::destroy (allo, elm); - ALOT::deallocate (allo, elm, 1); - } - - - public: - /** - * Create an instance of the adapter factory, - * forwarding to the embedded standard conforming allocator - * for object creation and destruction and memory management. - * @param allo (optional) instance of the C++ standard allocator - * used for delegation, will be default constructed if omitted. - * @remark the adapted standard allocator is assumed to be either a copyable - * value object, or even a mono-state; in both cases, a dedicated - * manager instance residing »elsewhere« is referred, rendering - * all those front-end instances exchangeable. - */ - StdFactory (Allo allo = Allo{}) - : Allo{std::move (allo)} - { } - - template - bool constexpr operator== (StdFactory const& o) const - { - return baseAllocator() == o.baseAllocator(); - } - template - bool constexpr operator!= (StdFactory const& o) const - { - return not (*this == o); - } - - - /** create new element using the embedded allocator */ - template - TY* - create (ARGS&& ...args) - { - if constexpr (std::is_same_v) - { - return construct (baseAllocator(), std::forward(args)...); - } - else - { - using XAlloT = typename AlloT::template rebind_traits; - auto xAllo = adaptAllocator(); - return construct (xAllo, std::forward(args)...); - } - } - - /** destroy the given element and discard the associated memory */ - template - void - dispose (TY* elm) - { - if constexpr (std::is_same_v) - { - destroy (baseAllocator(), elm); - } - else - { - using XAlloT = typename AlloT::template rebind_traits; - auto xAllo = adaptAllocator(); - destroy (xAllo, elm); - } - } - }; + /** common registration table and memory pool */ + class MemoryPool; } - ///////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1366 : the following code becomes obsolete in the long term + class TrackingAllocator + { + std::shared_ptr mem_; + + public: + /** can be default created to attach to a common pool */ + TrackingAllocator(); + + /** create a separate, marked memory pool */ + TrackingAllocator (Literal id); + + // standard copy operations acceptable + + + [[nodiscard]] void* allocate (size_t n); + void deallocate (void*) noexcept; + + + friend bool + operator== (TrackingAllocator const& a1, TrackingAllocator const& a2) + { + return a1.mem_ == a2.mem_; + } + friend bool + operator!= (TrackingAllocator const& a1, TrackingAllocator const& a2) + { + return not (a1 == a2); + } + + + /* ===== Diagnostics ===== */ + + static HashVal checksum (Literal pool =GLOBAL); + static size_t numAlloc (Literal pool =GLOBAL); + static size_t numBytes (Literal pool =GLOBAL); + + static EventLog log; + }; + + + template + class TrackAlloc + : public TrackingAllocator + { + public: + using TrackingAllocator::TrackingAllocator; + + /** cross-building for another type, using a common pool */ + template + TrackAlloc (TrackAlloc const& anchor) + : TrackingAllocator{anchor} + { } + + + /* ===== C++ standard allocator interface ===== */ + + using value_type = TY; + + [[nodiscard]] TY* allocate (size_t cnt); + void deallocate (TY*, size_t) noexcept; + }; + + + /** + * + */ + template + TY* + TrackAlloc::allocate (size_t cnt) + { + UNIMPLEMENTED ("type-sized alloc"); + } + + /** + * + */ + template + void + TrackAlloc::deallocate (TY* loc, size_t cnt) noexcept + { + UNIMPLEMENTED ("type-sized de-alloc"); + } /** * Placeholder implementation for a custom allocator @@ -251,5 +214,5 @@ namespace lib { -} // namespace lib +}} // namespace lib::test #endif /*LIB_TEST_TRACKING_ALLOCATOR_H*/ diff --git a/src/lib/test/tracking-dummy.hpp b/src/lib/test/tracking-dummy.hpp index e22a44d76..4f2d2f670 100644 --- a/src/lib/test/tracking-dummy.hpp +++ b/src/lib/test/tracking-dummy.hpp @@ -84,7 +84,10 @@ namespace test{ operator= (Dummy && oDummy) { if (&oDummy != this) - swap (*this, oDummy); + { + swap (*this, oDummy); + oDummy.setVal(0); + } return *this; } diff --git a/tests/library/test/test-tracking-test.cpp b/tests/library/test/test-tracking-test.cpp index fce10b7d5..05f97b2ad 100644 --- a/tests/library/test/test-tracking-test.cpp +++ b/tests/library/test/test-tracking-test.cpp @@ -30,11 +30,14 @@ #include "lib/test/tracking-dummy.hpp" #include "lib/test/tracking-allocator.hpp" #include "lib/format-cout.hpp" +#include "lib/format-util.hpp" +#include "lib/test/diagnostic-output.hpp"///////////////////////TODO #include using std::string; using util::toString; +using util::join; namespace lib { @@ -113,16 +116,81 @@ namespace test{ void demonstrate_checkObject () { - UNIMPLEMENTED ("dummy"); + CHECK (Dummy::checksum() == 0); + { + Dummy dum1; // picks a random positive int by default... + CHECK (0 < dum1.getVal() and dum1.getVal() <= 100'000'000); + CHECK (Dummy::checksum() == dum1.getVal()); + + Dummy dum2{55}; + CHECK (55 == dum2.getVal()); + CHECK (Dummy::checksum() == dum1.getVal() + 55); + + Dummy dum3{move (dum2)}; + CHECK (55 == dum3.getVal()); + CHECK (0 == dum2.getVal()); + + dum3.setVal (23); + CHECK (23 == dum3.getVal()); + + dum1 = move (dum3); + CHECK (23 == dum1.getVal()); + CHECK (0 == dum2.getVal()); + CHECK (0 == dum3.getVal()); + CHECK (Dummy::checksum() == 23); + + Dummy::activateCtorFailure (true); + try { + Dummy kabooom; + } + catch (int v) + { + CHECK (0 < v and v <= 100'000'000); + CHECK (Dummy::checksum() == 23 + v); + Dummy::checksum() -= v; + } + Dummy::activateCtorFailure (false); + CHECK (23 == dum1.getVal()); + CHECK (0 == dum2.getVal()); + CHECK (0 == dum3.getVal()); + CHECK (Dummy::checksum() == 23); + } + CHECK (Dummy::checksum() == 0); } /** @test custom allocator to track memory handling. */ void - demonstrate_checkAllocator () + demonstrate_checkAllocator() { - UNIMPLEMENTED ("allo"); + // setup a common lock for the tracking objects and -allocator + auto& log = TrackingAllocator::log; + Tracker::log.clear("Tracking-Allocator-Test"); + Tracker::log.joinInto(log); + + + CHECK (TrackingAllocator::checksum() == 0); + { + using SpyVec = std::vector>; + + SpyVec vec1(3); + + int v3 = vec1.back().val; +SHOW_EXPR(v3); +SHOW_EXPR(join(vec1)) + + SpyVec vec2; + vec2.emplace_back (move (vec1[2])); +SHOW_EXPR(join(vec1)) +SHOW_EXPR(join(vec2)) + + } + CHECK (TrackingAllocator::checksum() == 0); + + cout << "____Tracking-Allo-Log_________\n" + << util::join(Tracker::log, "\n") + << "\n───╼━━━━━━━━━━━━━━━━━╾────────"< + + + @@ -83514,7 +83517,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + + + @@ -83534,21 +83539,90 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - +

diese erweiterten Event-Log-Matches sind wohl etwas ad hoc

- -
+
- - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +