Commit graph

270 commits

Author SHA1 Message Date
a90b9e5f16 Library: uniform definition scheme for error-IDs
In the Lumiera code base, we use C-String constants as unique error-IDs.
Basically this allows to create new unique error IDs anywhere in the code.

However, definition of such IDs in arbitrary namespaces tends to create
slight confusion and ambiguities, while maintaining the proper use statements
requires some manual work.

Thus I introduce a new **standard scheme**
 * Error-IDs for widespread use shall be defined _exclusively_ into `namespace lumiera::error`
 * The shorthand-Macro `LERR_()` can now be used to simplify inclusion and referral
 * (for local or single-usage errors, a local or even hidden definition is OK)
2024-03-21 19:57:34 +01:00
59390cd2f8 Library: reorder some pervasively used includes
reduce footprint of lib/util.hpp
 (Note: it is not possible to forward-declare std::string here)

define the shorthand "cStr()" in lib/symbol.hpp

reorder relevant includes to ensure std::hash is "hijacked" first
2024-03-21 19:57:34 +01:00
47ae4f237c Scheduler-test: investigate and fix further memory manager problem
In-depth investigation and reasoning highlighted another problem,
which could lead to memory corruption in rare cases; in the end
I found a solution by caching the ''address'' of the current Epoch
and re-validating this address on each Epoch-overflow.

After some difficulties getting any reliable measurement for a Release-build,
it turned out that this solution even ''improves performance by 22%''

Remark-1: the static blockFlow::Config prevents simple measurements by
  just recompiling one translation unit; it is necessary to build the
  relevant parts of Vault-layer with optimisation to get reliable numbers

Remark-2: performing a full non-DEBUG build highlighted two missing
  header-inclusions to allow for the necessary template specialisations.
2023-12-28 02:13:24 +01:00
e0766f2262 Chain-Load: draft usage for Scheduler testing
- use a dedicated context "dropped off" the TestChainLoad instance
- encode the node-idx into the InvocationInstanceID
- build an invocation- and a planning-job-functor
- let planning progress over an lib::UninitialisedStorage array
- plant the ActivityTerm instances into that array as Scheduling progresses
2023-12-04 00:34:06 +01:00
685be1b039 Library/Application: consolidate Monitor API and usage
This is Step-2 : change the API towards application

Notably all invocation variants to support member functions
or a reference to bool flags are retracted, since today a
λ-binding directly at usage site tends to be more readable.

The function names are harmonised with the C++ standard and
emergency shutdown in the Subsystem-Runner is rationalised.

The old thread-wrapper test is repurposed to demonstrate
the effectiveness of monitor based locking.
2023-10-15 20:42:55 +02:00
77622a3f2d Library/Application: switch CallQueue_test 2023-10-05 01:17:58 +02:00
332ad0e920 Testsuite: fix regression
FamilyMember::allocateNextMember() was actually a post-increment,
so (different than with TypedCounter) here no correction is necessary


As an asside, WorkForce_test is sometimes unstable immediately after a build.
Seemingly a headstart of 50µs is not enough to compensate for scheduler leeway
2023-10-05 00:39:29 +02:00
6cd16a61a6 Library/Application: switch SubsystemRunner_test 2023-10-03 20:49:59 +02:00
fdd8e2d595 Library: identify reason for deadlock
- the deadlock was caused by leaking error state through the C-style lumiera_error

- but the reason for the deadlock lies in the »convenience shortcut«
  in the Object-Monitor scope guard for entering a wait state immediately.
  This function undermines the unlocking-guarantee, when an exception
  emanates from within the wait() function itself.
2023-09-30 23:55:42 +02:00
48d6f0fae3 Library/Application: switch Steam-Dispatcher to new thread-framework
TODO: SessionCommandFunction_test deadlocks!!
2023-09-30 04:13:22 +02:00
67b010ba7e Library: (re)introduce the distinction join / detach
While it would be straight forward from an implementation POV
to just expose both variants on the API (as the C++ standard does),
it seems prudent to enforce the distinction, and to highlight the
auto-detaching behaviour as the preferred standard case.

Creating worker threads just for one computation and joining the results
seemed like a good idea 30 years ago; today we prefer Futures or asynchronous
messaging to achieve similar results in a robust and performant way.

ThreadJoinable can come in handy however for writing unit tests, were
the controlling master thread has to wait prior to perform verification.

So the old design seems well advised in this respect and will be retained
2023-09-26 01:00:00 +02:00
ab7f506f4b Activity-Lang: failure will certainly not be signalled to the Job
doing so would contradict the fundamental architecture,
all kinds of failures and timeouts need to be handled within
Scheduler-Layer-2 rather.

Jobs are never aborted, nor do they need to know if and when they are invoked
2023-08-15 17:18:30 +02:00
23a6fbdf4f Scheduler: investigate modes of operation
- analysis of Activity usage
- derive possible memory management schemes
- research regarding asynchronous IO
- decision regarding the memory management scheme
2023-07-03 18:40:37 +02:00
3169ba88ad Scheduler: devise the arrangement of basic components
- define organisation of vault-layer namespaces
- define the ground plan of the scheduler implementation
2023-06-24 03:14:17 +02:00
130bc095d9 the new design takes the old name
The second design from 2017, based on a pipeline builder,
is now renamed `TreeExplorer` ⟼ `IterExplorer` and uses
the memorable entrance point `lib::explore(<seq>)`

✔
2023-06-22 20:23:55 +02:00
d109f5e1fb bye bye Monad (closes #1276)
after completing the recent clean-up and refactoring work,
the monad based framework for recursive tree expansion
can be abandoned and retracted.

This approach from functional programming leads to code,
which is ''cool to write'' yet ''hard to understand.''

A second design attempt was based on the pipeline and decorator pattern
and integrates the monadic expansion as a special case, used here to
discover the prerequisites for a render job. This turned out to be
more effective and prolific and became standard for several exploring
and backtracking algorithms in Lumiera.
2023-06-22 20:23:55 +02:00
42f4e403ac Job-Planning: rework of dispatcher and pipeline builder complete (see #1301)
An extended series of refactoring and partial rewrites resulted
in a new definition of the `Dispatcher` interface and completes
the buildup of a Job-Planning pipeline, including the ability
to discover prerequisites and compute scheduling deadlines.

At this point, I am about to ''switch to the topic'' of the `Scheduler`,
''postponing'' the completion of the `RenderDrive` until the related
questions regarding memory management and Scheduler interface are settled.
2023-06-22 03:55:09 +02:00
8c78e50730 Job-Planning: extended deadline integration test
- allow to configure the expected job runtime in the test spec
- remove link to EngineConfig and hard-wire the engine latency for now

... extended integration testing reveals two further bugs ;-)
... document deadline calculation
2023-06-21 04:04:11 +02:00
1f840730a0 Job-Planning: build and verify complete pipeline
- strip the builder
- add a terminal / front-end with convenience functions
- verify integration, incl multi-step prerequisites and deadlines
2023-06-20 01:46:44 +02:00
848bb6fb86 Job-Planning: implement handling of deadlines for prerequisites
...simple implementation
...decide *not* to cache the deadlines for now (possibly quadratic!)
...Test GREEN
2023-06-19 18:28:01 +02:00
b8309e5565 Job-Planning: define expectation for prerequisites 2023-06-19 16:58:32 +02:00
dc1bbfc918 Job-Planning: rework pipeline to enable dependency planning
This finishes the last series of refactorings; the basic concept
remains the same, but in the initial version we arranged the expander
function in the pipeline to maintain a Tuple (parent, child) for the
JobTickets. Unfortunately this turned out to be insufficient, since
JobTicket is effectively const and responsible for a complete Sement,
so there is no room to memorise a Deadline for the parent dependency.

This leads to the better idea to link the JobPlanning aggregators
themselves by parent-child references, which is possible since the
whole dependency chain actually sits in the stack embedded into the
Expander (in the pipeline)
2023-06-19 03:56:11 +02:00
9ef3d98de7 Job-Planning: replace FrameCoord by direct references
...in the hope that the Optimiser is able to elide those references entirely,
when (as is here the case) they point into another field of a larger object compound
2023-06-19 01:51:48 +02:00
a1c1456849 Job-Planning: dispose of FrameCoord in pipeline and Dispatcher interface
...as a preparation for solving a logical problem with the Planning-Pipeline;
it can not quite work as intended just by passing down the pair of
current ticket and dependent ticket, since we have to calculate a chained
calculation of job deadlines, leading up to the root ticket for a frame.

My solution idea is to create the JobPlanning earlier in the pipeline,
already *before* the expansion of prerequisites, and rather to integrate
the representation of the dependency relation direcly into JobPlanning
2023-06-18 03:50:48 +02:00
661d768fad Job-Planning: frame number now additionally required in FrameCoord
...which was the reason why the test failed;
the calculation works as expected


PS: rename JobPlanningSetup_test to JobPlanningPipeline_test
2023-06-17 03:10:57 +02:00
6228c623b4 Job-Planning: implement braindead deadline calculation
...using hard coded values instead of observation of actual runtimes,
but at least the calculation scheme (now relocated from TimeAnchor to JobPlanning)
should be a reasonable starting point.

TODO: test fails...
2023-06-16 04:09:38 +02:00
73a9e4495a Job-Planning: code up simplest use case 2023-06-16 01:50:11 +02:00
a551314e80 Job-Planning: start rework of the planning data aggregation
The initial implementation effort for Player and Job-Planning
has been reviewed and largely reworked, and some parts are now
obsoleted by the reworked alternative and can be disabled.

The basic idea will be retained though: JobPlanning is a
data aggregator and performs the final step of creating a Job
2023-06-15 03:51:07 +02:00
f84517547b Dispatcher-Pipeline: coordination of base tick and prerequisite expansion
- had to fix a logical inconsistency in the underlying Expander implementation
  in TreeExplorer: the source-pipeline was pulled in advance on expansion,
  in order to "consume" the expanded element immediately; now we retain
  this element (actually inaccessible) until all of the immediate
  children are consumed; thus the (visible) state of the PipeFrameTick
  stays at the frame number corresponding to the top-level frame Job,
  while possibly expanding a complete tree of flexible prerequisites

This test now gives a nice visualisation of the interconnected states
in the Job-Planning pipeline. This can be quite complex, yet I still think
that this semi-functional approach with a stateful pipeline and expand functors
is the cleanest way to handle this while encapsulating all details
2023-06-14 18:12:41 +02:00
08dfe1007c Dispatcher-Pipeline: verify the expansion of prerequisites
- fix a bug in the MockDispatcher, when duplicating the ExitNodes.
  A vector-ctor with curly braces will be interpreted as std::initializer_list

- add visualisation of the contents appearing at the end of the pipeline

*** something still broken here, increments don't happen as expected
2023-06-14 04:20:50 +02:00
542017aa65 Dispatcher-Pipeline: mocked Dispatcher implementation complete (closes: #1294)
`steam/engine/mock-dispatcher.hpp |cpp` now integrates this
''complete mock setup for render jobs and frame dispatching.''
The exising `DummyJob` has been slightly adapted and renamed
to `MockJob` and is tightly integrated with the other mocks.

The implementation of a `MockDispatcher` necessitated to change
the use of `MockJobTicket`. The initial attempts used a complete
mock implementation, but this approach turned out not to be viable.
Instead — based on the ideas developed for the mock setup —
now the prospective real implementation of `JobTicket` is available
and will be used by the mock setup too. Instead of a synthetic spec,
now a setup of recursively connected `ExitNode`(s) is used; the latter
seems to develop into some kind of Facade for the render node network.

Based on this mock setup, we can now demonstrate the (mostly) complete
Job-Planning pipeline, starting from a segmentation up to render jobs,
and verify proper connectivity and job invocation.
✔
2023-06-13 20:23:33 +02:00
0b9705692b Dispatcher-Pipeline: now (finally) able to implement MockDispatcher
MockSupport_test      : PASS
JobPlanningSetup_test : PASS(as far as defined)
2023-06-13 03:47:42 +02:00
122addbff5 Dispatcher-Pipeline: expected behaviour of (mock)Dispatcher 2023-06-13 00:15:16 +02:00
2031a58775 Dispatcher-Pipeline: decide upon the translation into portIDX
- has to be prepared / supported by the RenderEnvironmentClosure
- actual translation happens when building the Dispatcher-Pipeline
- implementation delegate through
    virtual size_t Dispatcher::resolveModelPort (ModelPort)
2023-06-12 19:21:14 +02:00
e6dcb6253c Dispatcher-Pipeline: resolve further problems with re-entrant allocation
...ouch this was insidious: the STL implementation for list does not
return a pointer to the element just allocated, but rather retrieves
and dereferences the back() / front() iterator after returning from emplace_back|front()

...which in case of re-entrant allocations is something wildly different
than the initial allocation. Thus a *cheap* and dirty placeholder implementation
just using a STL container is not possible, and we need at least
to code up likewise cheesy placeholder implementation by hand.
- separate allocation and ctor all
- use an inline buffer in the STL container
- explicitly handle ctor failures to discard allocation
- NOT THREADSAFE and likely WASTFUL in terms of performance


==> MockSupport_test now back to GREEN after complete refactoring
2023-06-12 17:21:41 +02:00
bf3e612c55 Dispatcher-Pipeline: create hook for self-validation
...later to be extended into the render nodes network
2023-06-12 01:18:59 +02:00
0933d2bba8 Dispatcher-Pipeline: simplify JobTicket and remove channel differentiation
The existing implementation of the Player from 2012~2015 inclduded
an additional differentiation by media channel (for multichannel media)
and would build a separate CalcStream for each channel.

The in-depth analysis conducted for the ongoing »Vertical Slice« effort
revealed that this differentiation is besides the point and would never
be materialised: Since -- by definition -- all media processing has
to be done by the engine, also the generation of the final output format
including any channel multiplexing will happen in render nodes.
The only exception would be when only a single channel of multichannel
media is extracted -- yet this case would then translate into a
dedicated ModelPort.

Based on this reasoning, a lot of complexity (and some contradictions)
within the JobTicket implementation can be removed -- together with
some further leftovers of the fist attempt to build JobTickets always
from a Mock specification (we now use construction by the Segment,
based on an ExitNode, which is the expected actual implementation
for production setup)
2023-06-12 00:04:45 +02:00
b18e79d077 Dispatcher-Pipeline: solve allocation of JobTicket instances
...by defining a new scheme for access to custom allocators
...and then passing a reference to such an accessor into the
   JobTicket ctor, thereby allowing the ticket istelf recursively
   to place further JobTicket instances into the allocation space

--> success, test passes (finally)
2023-06-11 04:37:38 +02:00
f25ec2f5ef Dispatcher-Pipeline: switch JobTicket creation to use ExitNode directly
Up to now, a draft/mock implementation was used, relying on a »spec tuple«,
which was fabricated by MockJobTicket. But with the introduction of
NodeGraphAttachment, the MockSequence now generates a nested ExitNode structure,
and thus the JobTicket will be created through the "real" ctor, and
no longer via MockJobTicket.

Thus it is possible to skip this whole interspersed »spec tuple«,
since ExitNode *is* already this aggregated / abstracted Spec
2023-06-10 04:52:40 +02:00
2c3b85a122 Dispatcher-Pipeline: allocate JobTicket in Segment
PROBLEM: can not implement Spec-generation, since
 - we must use a λ for internal allocation of JobTickets
 - but recursive type inference is not possible

Will thus need to abandon the Spec-Tuple and relocate this
traversal-and-generation code into JobTicket itself
2023-06-09 02:48:38 +02:00
c246c21e41 Dispatcher-Pipeline: remould Segment for on-demand JobTicket generation
Use another unit-test (FixtureSegment_test) to guide and cover
the transition from the existing fake-implementation to the
actual implementation, where the JobTicket will be generated
on-demand, from a NodeGraphAttachment
2023-06-08 03:21:43 +02:00
0c57a61545 Dispatcher-Pipeline: implement Generation of fake-ExitNodes
...similar to the Generation of complete JobTickets in the initial implementation
2023-06-08 00:28:44 +02:00
f6af4c6a16 Dispatcher-Pipeline: prepare test for the new NodeGraphAttachment
It turns out that the real (not mocked) implementation of JobTicket creation
is already required now for this planned (mock)Dispatcher setup;
moreover, this real implementation turns out to be almost identical
to the mock implementation written recently -- just nested structure
of prerequiste JobTickets need to be changed into a similar structur
of ExitNodes

-- as an aside: rearrange various tests to be more in-line
   with the envisioned architecture of playback and engine
2023-06-07 04:03:00 +02:00
3b2e5db7b4 Dispatcher-Pipeline: consider how to access render nodes from job
...this opens up yet another difficult question and a host of new problems
- how are prerequisites detected or arranged by the Builder
- how are prerequisites represented?
- what is an ExitNode in terms of implementation? A subclass of ProcNode?
- how will the actual implementation of JobTicket creation (on-demand) work?
- how to adapt the Mock implementation, while retaining the Specification
  for Segments and prerequisites?
2023-06-06 04:25:12 +02:00
7d5c32e6b6 Dispatcher-Pipeline: draft test for JobTicket access 2023-06-05 18:09:42 +02:00
4601c6350e Dispatcher-Pipeline: arrangement of builder types
...it turns out that we actually do not need to wrap TreeExplorer
on the builder types, because basically there is only a single active
builder type, and the complete processing pipeline can be assembled
in a single terminal function.

The type rebinding problem can thus be solved just by a simple
marker struct, which inherits from a template parameter
2023-06-04 02:01:07 +02:00
71ea10bf21 Dispatcher-Pipeline: implement the frame-tick core
splitting into a sequence of builder types seems to have done the trick
2023-06-03 18:38:37 +02:00
81ee9a2e67 Dispatcher-Pipeline: builder type rebinding problems
...hard to tackle...
The idea is to wrap the TreeExplorer builder, so that our specific
builder functions can delegated to the (inherited) generic builder functions
and would just need to supply some cleverly bound lambdas. However,
resulting types are recursive, which does not play nice with type inference,
and working around that problem leads to capturing a self reference,
which at time of invocation is already invalidated (due to moving the
whole pipeline into the final storage)
2023-06-03 03:44:22 +02:00
94fe4a4bec Dispatcher-Pipeline: draft builder-API
...which leads to the next daunting problems:
- we need some mocked ModelPort and DataSink placeholders
- we need a way how to inherit from a partial TreeExplorer pipeline
2023-06-02 05:32:15 +02:00
dda37365cc Dispatcher-Pipeline: direct implementation of frame-tick
start with demonstration of base technique in test setup
2023-06-01 18:09:26 +02:00