LUMIERA.clone/src/lib/allocation-cluster.hpp

166 lines
5.3 KiB
C++
Raw Normal View History

/*
ALLOCATION-CLUSTER.hpp - allocating and owning a pile of objects
2010-12-17 23:28:49 +01:00
Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de>
2010-12-17 23:28:49 +01: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.
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
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
*/
/** @file allocation-cluster.hpp
** 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.
**
** @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.
**
** @see allocation-cluster-test.cpp
** @see builder::ToolFactory
** @see frameid.hpp
*/
#ifndef LIB_ALLOCATION_CLUSTER_H
#define LIB_ALLOCATION_CLUSTER_H
2008-12-27 00:53:35 +01:00
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#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
#include <utility>
#include <vector>
namespace lib {
2008-12-27 01:04:20 +01: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.
* @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.
* @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!
* @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
*/
class AllocationCluster
: util::MoveOnly
{
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_;
};
public:
AllocationCluster ();
~AllocationCluster () noexcept;
2008-10-30 04:34:05 +01:00
template<class TY, typename...ARGS>
TY&
create (ARGS&& ...args)
{
return * new(allotMemory (sizeof(TY))) TY (std::forward<ARGS> (args)...);
}
template<typename X>
Allocator<X>
getAllocator()
{
return Allocator<X>{this};
}
2008-10-30 04:34:05 +01:00
/* === diagnostics === */
size_t
numExtents() const
{
UNIMPLEMENTED ("Allocation management");
}
size_t
numBytes() const
{
UNIMPLEMENTED ("Allocation management");
}
private:
/**
* 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-20 03:13:02 +02:00
//-----implementation-details------------------------
} // namespace lib
#endif /*LIB_ALLOCATION_CLUSTER_H*/