Commit graph

31 commits

Author SHA1 Message Date
afa7ca2e4d Upgrade: switch to C++23 (see #1245)
The Lumiera »Reference Platform« is now upgraded to Debian/Buster, which provides GCC-14 and Clang-20.
Thus the compiler support for C++20 language features seems solid enough, and C++23,
while still in ''experimental stage'' can be seen as a complement and addendum.

This changeset
 * upgrades the compile switches for the build system
 * provides all the necessary adjustments to keep the code base compilable

Notable changes:
 * λ-capture by value now requires explicit qualification how to handle `this`
 * comparison operators are now handled transparently by the core language,
   largely obsoleting boost::operators. This change incurs several changes
   to implicit handling rules and causes lots of ambiguities — which typically
   pinpoint some long standing design issues, especially related to MObjects
   and the ''time entities''. Most tweaks done here can be ''considered preliminary''
 * unfortunately the upgraded standard ''fails'' to handle **tuple-like** entities
   in a satisfactory way — rather an ''exposition-only'' concept is introduced,
   which applies solely to some containers from the STL, thereby breaking some
   very crucial code in the render entities, which was built upon the notion of
   ''tuple-like'' entities and the ''tuple protocol''. The solution is to
   abandon the STL in this respect and **provide an alternative implementation**
   of the `apply` function and related elements.
2025-06-19 01:52:55 +02:00
8069c874f1 Invocation: develop a concept for handling parameter data
...as part of the rendering process, executed on top of the
low-level-model (Render Node network) as conceived thus far.

Parameter handling could be ''encoded'' into render nodes altogether,
or, at the other extreme, an explicit parameter handling could be specified
as part of the Render Node execution. As both extremes will lead to some
unfavourable consequences, I am aiming at a middle ground: largely, the
''automation computation'' will be encoded and hidden within the network,
implying that this topic remains to be addressed as part of defining
the Builder semantics and implementation. Yet in part the required
processing structure can be foreseen at an abstract level, and thus
the essential primitive operations are specified explicitly as part
of the Render Node definition. Notably the ''standard Weaving Pattern''
will include a ''parameter tuple'' into each `FeedManifold` and require
a binding function, which accepts this tuple as first argument.

Moreover — at implementation level, a library facility must be provided
to support handling of ''arbitrary heterogeneous data values'' embedded
directly into stack frame memory, together with a type-safe compile-time
overlay, which allows the builder to embed specific ''accessor handles''
into functor bindings, even while the actual storage location is not
yet known at that time (obviously, as being located on the stack).

__Note__: a recurring topic is how to return descriptor objects from builder functions; for this purpose, I am adjusting the semantics of `lib/nocopy.hpp` to be more specific...
2024-12-09 22:10:11 +01:00
806db414dd Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
 * there is no entity "Lumiera.org" which holds any copyrights
 * Lumiera source code is provided under the GPL Version 2+

== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''

The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!

The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
1705c40dc2 Invocation: rearrange SeveralBuilder policy
redefine the policy for `lib::SeveralBuilder` to be a template-template parameter.
In fact it should have been this way from start, yet defining this kind of
very elaborate code bottom-up lets you sometime miss the wood for the trees

So to restate: `lib::SeveralBuilder` takes a ''policy template,''
which then in turn will be instantiated with the same types `I` (interface)
and `E` (element type) used on `SeveralBuilder` itself. Obviously, there can be
further types involved and thus additional type parameters may be necessary,
notably the ''Allocator'' — yet these are better injected when ''defining''
the policy template itself.

The default binding for this policy template is defined as `allo::HeapOwn`,
which causes the builder to allocate the storage extents through the standard
heap allocator, and for the created `lib::Several` to take full ownership of
embedded objects, invoking their destructors when falling out of scope.
2024-07-17 01:43:17 +02:00
f632701f48 Library: lib::Several complete and tested (see #473)
As a replacement for the `RefArray` a new generic container
has been implemented and tested, in interplay with `AllocationCluster`
 * the front-end container `lib::Several<I>` exposes only a reference
   to the ''interface type'' `I`, while hiding any storage details
 * data can only be populated through the `lib::SeveralBuilder`
 * a lot of flexibility is allowed for the actual element data types
 * element storage is maintained in a storage extent, managed through
   a custom allocator (defaulting to `std::allocator` ⟹ heap storage)
2024-06-19 19:40:03 +02:00
cf6abf6a3b Library: observe allocator limits on exponential expansion
The `SeveralBuilder` employs the same tactic as `std::vector`,
by over-allocating a reserve buffer, which grows in exponential
increments, to amortise better the costs of re-allocation.

This tactic does not play well with space limited allocators
like `AllocationCluster` however; it is thus necessary to provide
an extension point where the actuall allocator's limitation can be
queried, allowing to use what is available as reserve, but not more.

With these adaptations, a full usage cycle backed by `AllocationCluster`
can be demonstrated, including variations of dynamic allocation adjustment.
2024-06-19 17:35:46 +02:00
39e9ecd90e Library: AllocationCluster and SeveralBuilder logic tweaks
...identified as part of bug investigation

 * make clear that reserve() prepares for an absolute capacity
 * clarify that, to the contrary, ensureStorageCapaciy() means the delta

Moreover, it turns out that the assertion regarding storage limits
triggers frequently while writing the test code; so we can conclude
that the `AllocationCluster` interface lures into allocating without
previous check. Consequently, this check now throws a runtime exception.

As an aside, the size limitation should be accessible on the interface,
similar to `std::vector::max_size()`
2024-06-19 15:45:12 +02:00
9709309186 Library: setup adaptor for dynamic adjustments
By means of the extension point, which produces a dedicated policy
for use with `AllocationCluster`, it becomes possible to use the
specialised API to adjust the latest allocation in the cluster.
When this is not actually usable, the policy will fall back
on the standard implementation (which is wasteful when
applied to `AllocationCluster`, since memory for the
obsoleted, smaller blocks not de-allocated then...
2024-06-19 03:26:36 +02:00
d327094603 Library: draft a scheme to configure lib::Several with a custom allocator
Phew... this was a tough one — and not sure yet if this even remotely works...

Anyway, the `lib::SeveralBuilder` is already prepared for collaboration with a
custom allocator, since it delegates all memory handling through a base policy,
which in turn relies on std::allocator_traits.

The challenge however is to find a way...
 * to make this clear and easy to use
 * to expose an extension point for specific tweaks
 * and to make all this work without excessive header cross dependencies
2024-06-16 04:22:28 +02:00
bb164e37c8 Library: allow for dynamic adjustments in AllocationCluster
This is a low-level interface to allow changing the size of
the currently latest allocation in `AllocationCluster`; a client
aware of this capability can perform a real »in-place re-alloc«,
assuming the very specific usage constraints can be met.

`lib::Several<X>` will use this feature when attached to an
`AllocationCluster`; with this special setup, an previously
unknown number of non-copyable objects can be built without
wasting any storage, as long as the storage reserve in the
current extent of the `AllocationCluster` is sufficient.
2024-06-16 04:22:28 +02:00
24b3e5ceba Library: work out adaptor solution for custom allocator
...turns out to be rather challenging, due to the far reaching requirements
 * the default case (heap allocation) ''must work out-of-the box''
 * optionally a C++ standard conformant `Allocator` can be adapted
 * which works correct even in case this allocator is ''not a monostate''
 * **essential requirement** is to pass an `AllocationCluster` reference directly
 * need a ''generic extension point'' to adapt to similar elaborate custom schemes

__Note__: especially we want to create a direct collaboration between the allocation policy and the underlying allocator to allow support for a dedicate ''realloc operation''
2024-06-07 03:36:25 +02:00
db4fbde201 Library: adapt further AllocationCluster tests
...especially demonstrate that destructors
can optionally be invoked or not invoked...
2024-05-27 21:21:03 +02:00
178107e8b9 Library: enable empty-base optimisation for allocator
...this is an important detail: quite commonly, a custom allocator
is actually implemented as monostate, to avoid bloating every client container
with a backlink pointer; by inheriting the `StdFactory` adapter from the
allocator, the empty-base optimisation can be exploited.

In the standard case thus LinkedElements is the same size as a single
pointer, which is already exploited at several places in the code base.
Notably `AllocationCluster` uses a »virtual overlay« to dress-up the
position pointer as `LinkedElements`, allowing to delegate most of the
administration and memory management to existing and verified code.


With this adjustments, `LinkedElements` pass the tests again
and the rework of `AllocationCluster` is considered complete.
2024-05-27 19:02:31 +02:00
08e0f52e61 Library: low-level implementation internals covered
...including overflow into new extents, alignment padding
and chaining and invocation of destructors.
2024-05-25 20:01:23 +02:00
be398e950a Library: better let C++ handle the destructors
...what I've implemented yesterday is effectively the same functionality
as provided automatically by the C++ object system when using a virtual destructor.
Thus a much cleaner solution is to turn `Destructor` into a interface
and let C++ do all the hard work.

Verified in test: works as intended
2024-05-25 19:27:17 +02:00
71d5851701 Library: implement optional invocation of destructors
This is the first draft, implementing the invocation explicitly
through a trampoline function. While it seems to work,
the formulation can probably be simplified....
2024-05-25 05:14:36 +02:00
13e22f315a Library: clarify details of the low-level allocation
- rather accept hard-wired limits than making the implementation excessively generic
- by exploiting the layout, the administrative overhead can be reduced significantly
- the trick with the "virtual managment overlay" allows to hand-off most of the
  clean-up work to C++ destructor invocation
- it is important to verify these low-level arrangements explicitly by unit-test
2024-05-19 17:53:51 +02:00
72aea53ac3 Library: idea for an extent management mechanism
* this is pure old-style low-level trickery
 * using a layout trick, the `AllocationCluster`
   can be operated with the bare minimum of overhead
 * this trick relies on the memory layout of `lib::LinkedElements`
2024-05-18 02:35:20 +02:00
c623298ac8 Library: draft standard case for actual memory allocation
- attempt to use the minimal possible storage for the management itself
- rely on the `std::align()` function to do the actual placement
2024-05-16 02:47:01 +02:00
eeda3aaa56 Library: remove elaborate allocation logic
...due to the decision to use a much simpler allocation scheme
to increase probability for actual savings, after switching the API
and removing all trading related aspects, a lot of further code is obsoleted
2024-05-16 01:46:41 +02:00
13f51c910c Library: work out ramifications of the changed design
Notably this raises the difficult question,
whether to ensure **invocation of destructors**.

Not invoking dtors ''breaks one of the most fundamental contracts''
of the C++ language — yet the infrastructure to invoke dtors in such
a heterogeneous cluster of allocations creates a hugely significant
overhead and is bound to poison the caches (objects to be deallocated
typically sit in cold memory pages).

What makes this decision especially daunting is the fact that the
low-level-Model can be expected to be one of the largest systemic
data structures (letting aside the media buffers).

I am leaning towards a compromise: turn down this decision
towards the user of the `AllocationCluster`
2024-05-15 19:59:05 +02:00
fd49c68096 Library: draft a simpler STL complient allocation interface
After some analysis, it became clear that the existing code for
`AllocationCluster` (while in itself valid) will likely miss the point
for the expected usage in the low-level Model: most segments of the
model will be rather small, and thus there is not enough potential for
amortisation when using such a per-type and per-segment scheme;
a rather simplistic linear allocator will be sufficient.

On the other hand, with the current C++ standard it is easy to provide
a complient allocator implementation for STL containers, and thus the
interface should be retro-fitted accordingly.
2024-05-15 01:38:16 +02:00
856d8a3b51 Library: allow to reverse intrusive single linked list
Looks like we'll actually retain and use this low-level solution
in cases where we just can not afford heap allocations but need
to keep polymorphic objects close to one another in memory.

Since single linked lists are filled by prepending, it is rather
common to need the reversed order of elements for traversal,
which can be achieved in linear time.

And while we're here, we can modernise the templated emplacement functions
2023-04-20 18:53:17 +02:00
f06038828c GCC-7: integrate recent clean-up and refactoring work (lib::Depend)
# Conflicts:
#	src/lib/error-exception.cpp
#	src/lib/error.hpp
#	src/lib/opaque-holder.hpp
#	src/lib/wrapper.hpp
#	src/proc/mobject/session/sess-manager-impl.hpp
2018-04-27 02:23:20 +02:00
3296148dad pre-C++17: remove remaining old-style (dynamic) exception specifications 2018-04-26 12:07:08 +02:00
685a9b84ee Library: replace boost::noncopyable by our own library solution
Benefits
 - get rid of yet another pervasive Boost dependency
 - define additional more fine grained policies (move only, clonable)
2018-03-24 05:35:13 +01:00
cd8844b409 clean-up: kill Boost scoped_ptr
std::unique_ptr is a drop-in replacement
2017-01-05 00:56:46 +01:00
7faa2e784d CLang-Compatibility: zero argument ctor now treated as function definition
previous versions used to resolve this ambiguity in favour of a ctor call,
but now the compiler treats such constructs as function definition;
this is reasonable, since C++11 introduced the notion of a "generalised
initialisation", which is always written as a (possibly empty) list
in braces.

In these specific cases here, we just omit the empty parens
2014-08-26 03:31:03 +02:00
e35a45a65e tricky header reordering to support a hackish-workaround (#944)
right now we have to defeat an unfortunate static assertion in
the standard library, which is expected to go away in the future.
We use a hack to hijack the problematic definition with the preprocessor,
which requires our header to be first.
2014-08-17 08:03:21 +02:00
3ef1fb7697 linked list helper template finished and passes test 2012-10-10 05:20:14 +02:00
7fc462209e some naming cleanup and namespace indentation fixes 2010-12-18 00:58:19 +01:00
Renamed from src/lib/allocationcluster.hpp (Browse further)