2008-10-18 02:32:34 +02:00
|
|
|
/*
|
2010-12-18 00:58:19 +01:00
|
|
|
ALLOCATION-CLUSTER.hpp - allocating and owning a pile of objects
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2008, Hermann Vosseler <Ichthyostega@web.de>
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
2010-12-17 23:28:49 +01:00
|
|
|
published by the Free Software Foundation; either version 2 of
|
|
|
|
|
the License, or (at your option) any later version.
|
|
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
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.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
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.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
*/
|
|
|
|
|
|
2010-12-18 00:58:19 +01:00
|
|
|
/** @file allocation-cluster.hpp
|
2008-10-18 02:32:34 +02:00
|
|
|
** Memory management for the low-level model (render nodes network).
|
|
|
|
|
** The model is organised into temporal segments, which are considered
|
|
|
|
|
** to be structurally constant and uniform. The objects within each
|
|
|
|
|
** segment are strongly interconnected, and thus each segment is
|
|
|
|
|
** being built in a single build process and is replaced or released
|
|
|
|
|
** as a whole. AllocationCluster implements memory management to
|
2008-10-20 03:13:02 +02:00
|
|
|
** support this usage pattern.
|
|
|
|
|
**
|
2024-05-14 23:37:49 +02:00
|
|
|
** @warning in rework 5/2024 — with the goal to simplify the logic,
|
|
|
|
|
** remove all thread safety and make the implementation
|
|
|
|
|
** usable as standard conformant allocator for STL.
|
2008-10-18 02:32:34 +02:00
|
|
|
**
|
2010-12-18 00:58:19 +01:00
|
|
|
** @see allocation-cluster-test.cpp
|
2008-10-18 02:32:34 +02:00
|
|
|
** @see builder::ToolFactory
|
|
|
|
|
** @see frameid.hpp
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2010-12-18 00:58:19 +01:00
|
|
|
#ifndef LIB_ALLOCATION_CLUSTER_H
|
|
|
|
|
#define LIB_ALLOCATION_CLUSTER_H
|
2008-10-18 02:32:34 +02:00
|
|
|
|
2008-12-27 00:53:35 +01:00
|
|
|
#include "lib/error.hpp"
|
2018-03-24 05:35:13 +01:00
|
|
|
#include "lib/nocopy.hpp"
|
2008-12-26 04:25:01 +01:00
|
|
|
#include "lib/sync-classlock.hpp"
|
2009-07-04 00:24:55 +02:00
|
|
|
#include "lib/scoped-holder.hpp"
|
2010-12-03 03:13:57 +01:00
|
|
|
#include "lib/scoped-holder-transfer.hpp"
|
2008-10-20 03:13:02 +02:00
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
#include <utility>
|
2014-08-17 08:03:21 +02:00
|
|
|
#include <vector>
|
|
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace lib {
|
2008-12-27 01:04:20 +01:00
|
|
|
|
|
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
/**
|
|
|
|
|
* A pile of objects sharing common allocation and lifecycle.
|
|
|
|
|
* AllocationCluster owns a number of object families of various types.
|
|
|
|
|
* Each of those contains a initially undetermined (but rather large)
|
|
|
|
|
* number of individual objects, which can be expected to be allocated
|
|
|
|
|
* within a short timespan and which are to be released cleanly on
|
2008-10-30 04:34:05 +01:00
|
|
|
* destruction of the AllocationCluster. We provide a service creating
|
|
|
|
|
* individual objects with arbitrary ctor parameters.
|
2008-10-18 02:32:34 +02:00
|
|
|
* @warning make sure the objects dtors aren't called and object references
|
|
|
|
|
* aren't used after shutting down a given AllocationCluster.
|
2008-10-30 04:34:05 +01:00
|
|
|
* @todo implement a facility to control the oder in which
|
|
|
|
|
* the object families are to be discarded. Currently
|
|
|
|
|
* they are just purged in reverse order defined by
|
|
|
|
|
* the first request for allocating a certain type.
|
2008-12-28 05:20:35 +01:00
|
|
|
* @todo should we use an per-instance lock? We can't avoid
|
|
|
|
|
* the class-wide lock, unless also the type-ID registration
|
|
|
|
|
* is done on a per-instance base. AllocationCluster is intended
|
|
|
|
|
* to be used within the builder, which executes in a dedicated
|
|
|
|
|
* thread. Thus I doubt lock contention could be a problem and
|
|
|
|
|
* we can avoid using a mutex per instance. Re-evaluate this!
|
2012-04-30 04:28:16 +02:00
|
|
|
* @todo currently all AllocationCluster instances share the same type-IDs.
|
|
|
|
|
* When used within different usage contexts this leads to some slots
|
|
|
|
|
* remaining empty, because not every situation uses any type encountered.
|
|
|
|
|
* wouldn't it be desirable to have multiple distinct contexts, each with
|
|
|
|
|
* its own set of Type-IDs and maybe also separate locking?
|
|
|
|
|
* Is this issue worth the hassle? //////////////////////////////TICKET #169
|
2008-10-18 02:32:34 +02:00
|
|
|
*/
|
|
|
|
|
class AllocationCluster
|
2024-05-14 23:37:49 +02:00
|
|
|
: util::MoveOnly
|
2008-10-18 02:32:34 +02:00
|
|
|
{
|
|
|
|
|
|
2024-05-14 23:37:49 +02:00
|
|
|
template<typename X>
|
|
|
|
|
struct Allocator
|
|
|
|
|
{
|
|
|
|
|
using value_type = X;
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] X* allocate (size_t n) { return mother_->allot<X>(n); }
|
|
|
|
|
void deallocate (X*, size_t) noexcept { /* rejoice */ }
|
|
|
|
|
|
|
|
|
|
Allocator(AllocationCluster* m) : mother_{m} { }
|
|
|
|
|
private:
|
|
|
|
|
AllocationCluster* mother_;
|
|
|
|
|
};
|
|
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
public:
|
|
|
|
|
AllocationCluster ();
|
2023-04-20 18:53:17 +02:00
|
|
|
~AllocationCluster () noexcept;
|
2008-10-18 02:32:34 +02:00
|
|
|
|
2008-10-30 04:34:05 +01:00
|
|
|
|
2023-04-20 18:53:17 +02:00
|
|
|
template<class TY, typename...ARGS>
|
2008-10-18 02:32:34 +02:00
|
|
|
TY&
|
2023-04-20 18:53:17 +02:00
|
|
|
create (ARGS&& ...args)
|
2008-10-18 02:32:34 +02:00
|
|
|
{
|
2024-05-14 23:37:49 +02:00
|
|
|
return * new(allotMemory (sizeof(TY))) TY (std::forward<ARGS> (args)...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename X>
|
|
|
|
|
Allocator<X>
|
|
|
|
|
getAllocator()
|
|
|
|
|
{
|
|
|
|
|
return Allocator<X>{this};
|
2008-10-18 02:32:34 +02:00
|
|
|
}
|
2008-10-30 04:34:05 +01:00
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
/* === diagnostics === */
|
|
|
|
|
|
2024-05-15 19:59:05 +02:00
|
|
|
size_t
|
|
|
|
|
numExtents() const
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED ("Allocation management");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t
|
|
|
|
|
numBytes() const
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED ("Allocation management");
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
|
2008-10-23 23:08:27 +02:00
|
|
|
private:
|
2024-05-14 23:37:49 +02:00
|
|
|
/**
|
|
|
|
|
* portion out the requested amount of memory,
|
|
|
|
|
* possibly claiming a new pool block.
|
|
|
|
|
*/
|
|
|
|
|
void*
|
|
|
|
|
allotMemory (size_t bytes)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED ("actual memory management");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename X>
|
|
|
|
|
X*
|
|
|
|
|
allot (size_t cnt =1)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<X*> (allotMemory (cnt * sizeof(X)));
|
|
|
|
|
}
|
2008-10-18 02:32:34 +02:00
|
|
|
};
|
2008-10-20 03:13:02 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----implementation-details------------------------
|
|
|
|
|
|
2012-04-30 04:28:16 +02:00
|
|
|
|
2008-10-18 02:32:34 +02:00
|
|
|
} // namespace lib
|
2023-04-20 18:53:17 +02:00
|
|
|
#endif /*LIB_ALLOCATION_CLUSTER_H*/
|