Commit graph

3921 commits

Author SHA1 Message Date
c0dca2d978 DockAccess: add lookup-by-Type function to PanelManager
...now the mess multiplies
2018-09-14 21:06:12 +02:00
987aad44c1 DockAccess: add ability to retrieve a panel via PanelManager (#1144)
This is only a premature hack, since the whole structure of PanelManager is somewhat broken.
Moreover, the ViewLocator is not really ready for use yet, so this hack at least
allows us to "reach into" a top-level window and "grab" the pannel we need.
2018-09-14 21:06:12 +02:00
e7e09a642b NotificateDisplay: delegate view allocation through a functor 2018-09-14 21:06:12 +02:00
42cbc9219f NotificateDisplay: link to a widget for error log display
The ErrorLogWidget is allocated and placed elsewhere
and not owned by the NotificationHub controller.
2018-09-14 21:06:12 +02:00
a74dc596ce WLink: finished incl. exception handling guarantees and documentation 2018-09-14 21:06:12 +02:00
ae26012bf5 WLink: implement copy operations
swap-based implementation
not sure if attachTo() should be noexcept
2018-09-14 21:06:12 +02:00
22cdfbff2c WLink: fill in some documentation 2018-09-14 21:06:12 +02:00
a15951b036 WLink: implement connecting / reconnecting 2018-09-14 21:06:12 +02:00
0c29bd7c92 WLink: implement the basic tracking functionality 2018-09-14 21:06:12 +02:00
c47e3d0210 WLink: draft basic behaviour 2018-09-14 21:06:12 +02:00
e829a74edf NotificationDisplay: draft idea of managed link-to-widget
a smart-reference based on sigc::trackable
2018-09-14 21:06:12 +02:00
36abe4567e NotificationDisplay: define the actual controller behaviour to be implemented
this is specification work; for now the stubs are marked UNIMPLEMENTED
2018-09-14 21:06:12 +02:00
b7c3764ae8 NotificationDisplay: wire NotificationHub-Controller with the global ID 2018-09-14 21:06:12 +02:00
c2c25f8134 NotificationDisplay: define and include the unique error-Log ID 2018-09-14 21:06:12 +02:00
53c47a6fcc Assets: verify creation of ErrorLog meta-Asset 2018-09-14 21:06:12 +02:00
f872e22216 Assets: draft how the global ErrorLog asset could be created 2018-09-14 21:06:12 +02:00
928b4372e0 Assets: investigating the unclear distinction between asset::Struct and asset::Meta (#1156)
including a kind-of Bugfix: the ctor of TimeGrid erroneously categorised it as asset::Kind STRUCT
2018-09-14 21:06:12 +02:00
1d69bb9050 NotificationDisplay: define a new ErrorLog asset
...for now to serve as placeholder type, used as anchor for the corresponding UI display widget
2018-09-14 21:06:12 +02:00
5475839a49 NotificationDisplay: the question where to define the entity-ID 2018-09-14 21:06:12 +02:00
12244afc90 NotificationDisplay: fill in some default implementation for the controller 2018-09-14 21:06:12 +02:00
0c8151cb2f NotificationDisplay: decide upon the architecture for handling notification messages (#1102)
* have a dedicated "information hub" controller, which acts a receiver of "error log messages" on the UI-Bus
 * let that controller in turn allocate an apropriate view on demand
2018-09-14 21:06:12 +02:00
06b3c382f3 DemoGuiRoundtrip: expand on that idea (#1099) and start analysis how to create that UI component
The goal is to build a (in itself completely meaningless) ping-pong interaction
between the UI and Proc-Layer, for the purpose of driving the integration ahead.

The immediate challenge is how to create and place an apropriate "GuiComponentView",
i.e. a Tangible, which is connected to the UI-Bus with an predictable EntryID.
And the problem is to get that settled right now, without building the envisioned
generic framework for View allocation in the UI. When this is achieved,
it should be a rather small step to actually send those notifications over
the UI-Bus, which is basically implemented and ready by now.
2018-09-14 21:06:12 +02:00
3a100972d7 UI-Lifecycle: send up a dummy notification message to indicate start of content population
right now this will just end up in the log, since not even the
notification display is implemented beyond the GuiNotification-facade.

Anyway, we get some kind of communication now for real, in the actual application
2018-08-04 19:07:21 +02:00
4e77a28112 UI-Lifecycle: use dummy-mechanism to get the new command executed
...because due of #211, we usually don't execute commands yet.
For now there is only the backdoor to prefix the command-ID with "test"

With this change, the TODO message appears now immediately after GUI start!
2018-08-04 18:45:58 +02:00
d58890e2d5 UI-Lifecycle: define a new Proc-Command to implement the population trigger (#1150) 2018-08-04 17:10:04 +02:00
eca06a8309 UI-Lifecycle: build trigger point for content population into InteractionDirector (closes #1151)
In the end, I decided against building a generic service here,
since it pretty much looks like a one-time problem.

Preferrably UI content will be pushed or pulled on demand,
rather than actively coding content from within the UI-Layer
2018-08-04 16:02:00 +02:00
d3daed9a18 UI-Lifecycle: invstigate where to issue the trigger (#1151) 2018-08-02 19:59:26 +02:00
9a39781667 UI-Lifecycle: draft a plan how to trigger content population
...and while doing so, also re-check the state of the GTK toolkit initialisation.
Looks like we're still future-proof, while cunningly avoiding all this
Gnome-style "Application" blurb
2018-07-28 19:01:23 +02:00
0c5a0fed6a UI-Lifecycle: verify and rectify start-up sequence (#1147)
...still not entirely decided yet where to plant the mechanism for
UI content retrieval (#1150)
2018-07-14 19:39:00 +02:00
c24778132e After a long break (LAC.2018 Berlin) -- start planning the next steps
I will abandon work on the ViewSpec DSL in current shape (everything fine with that)
and instead work on a general UI start-up and content population sequence.
From there, my intention is to return to the docks, the placement of views
and then finally to the TimelineView
2018-07-12 21:32:41 +02:00
30db188064 DockAccess: fix compilation due to renaming
the renamed entity DockArea is still defunct, but also not used yet
2018-06-17 15:19:48 +02:00
5cac40654f DockAccess: draft code reorganisation (#1144) 2018-06-17 15:09:52 +02:00
8097485dbf ViewSpec: integrate the simple View access case (Unit test PASS)
This finishes the first round of design drafts in this area.
Right now it seems difficult to get any further, since most of
the actual view creation and management in the UI is not yet coded.
2018-06-15 18:02:08 +02:00
800fc5915a ViewSpec: recast the ElementAccess API to work around the design problem
...it is not really solved, rather postponed.
But who knows. Maybe it's already good enough...
2018-06-15 16:42:51 +02:00
2e8bc9227a ViewSpec: analysis of design alternatives
looks like I'm trapped with the choice between a convoluted API design
and an braindead and inefficient implementation. I am leaning towards the latter
2018-06-15 01:51:10 +02:00
f55a8f606b ...one month later: pick up after the LAC.18 Berlin
...happened to be completely absorbed by the preparations
for my workshop about Yoshimi and musical presets
2018-06-14 17:02:34 +02:00
363d24ba91 ViewSpec: unsuccessful atempt to implement the allocator token
looks like we're hitting a design mismatch here....

...and unfortunately I have to abandon this task now and concentrate
on preparation of my talk at LAC.2018 in June
2018-06-14 15:13:06 +02:00
f1ea503cfa ViewSpec: singleton factory to organise the actual ViewSpec DSL tokens
it seems apropriate to move the base definition of gui::idi::Descriptor<VIEW>
into view-spec-dsl.hpp and only retain the actual DSL definitions in id-scheme.hpp
2018-05-06 01:45:38 +02:00
852a3521db Static-Init: switch lib::Depend to embed the factory as Meyer's Singleton (#1142)
this is a (hopefully just temporary) workaround to deal with static initialisation
ordering problems. The original solution was cleaner from a code readability viewpoint,
however, when lib::Depend was used from static initialisation code, it could
be observed that the factory constructor was invoked after first use.

And while this did not interfer with the instance lifecycle management itself,
because the zero-initialisation of the instance (atomic) pointer did happen
beforehand, it would discard any special factory functions installed from such
a context (and this counts as bug for my taste).
2018-05-01 18:49:20 +02:00
f99637285a GCC-7: fix segfault in static init
seemingly this code was brittle: GCC-7 treats int64_t as long,
which leads to preferring the template specialisation over the
explicit version of the operator* -- which means the template
instantiation invokes itself.
2018-04-28 03:02:02 +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
eca7aa1451 GCC-7: minor compilation fixes 2018-04-26 12:19:45 +02:00
3296148dad pre-C++17: remove remaining old-style (dynamic) exception specifications 2018-04-26 12:07:08 +02:00
d0538a55ff ViewSpec: implement the generic access function in ViewLocator
still missing: internal wiring from the allocation token(s) of the DSL
into the ElementAccess service designed last week.
2018-04-15 03:07:54 +02:00
ba3d9e57b5 ViewSpec: draft a way to code an integration test for ViewLocator (#1129)
The original goal for #1129 (ViewSpecDSL_test) is impossible to accomplish,
at least within our existing test framework. Thus I'll limit myself to coding
a clean-room integration test with purely synthetic DSL definitions and mock widgets
2018-04-15 01:39:46 +02:00
c9dc9264b4 Library: fix possible follow-up error in errorhandling
usually the ID is hard coded, but when re-throwing errors, it might be
from "somewhere else", which means it is possibly a NULL ptr.
In those cases we fall back to the cannonical ID of the error class.
2018-04-14 03:24:45 +02:00
a565fc3321 ElementAccess: rearrange files according to namespace 2018-04-14 02:06:31 +02:00
4071a58454 ElementAccess: fix first unit test case
ouch, the typedef Base /is/ already a pointer...
2018-04-14 01:59:41 +02:00
bf9fcc3b2e ElementAccess: make the metaprogramming helper part of lib::Variant
...since such a metafunction makes sense, generally.
Get me the first of the possible variant types, which fulfils predicate _P_
2018-04-13 04:19:50 +02:00
22f50b1b00 ElementAccess: streamline error cases
My understanding is that in the standard use case, we precisely know what to expect
and just go ahead and perform the conversion. Thus it is pointless to introduce
fine grained distinctions. When the access fails, this always indicates some broken
application logic, and just raises an error.
2018-04-13 03:29:08 +02:00
ac4f0bc6db ElementAccess: possibly working solution based on lib::variant
With this solution, somewhere deep down within the implementation
the knowledge about the actual result type would be encoded into
the embedded VTable within a lib::variant. At interface level,
ther will be a double dispatch based on that result type
and the desired result type, leading either to a successful
access or an error response.
2018-04-13 02:39:46 +02:00
35ea547fd1 ElementAccess: (WIP) another unsuccessful attempt
Problem is, we can not even compile the conversion in the "other branch".
Thus we need to find some way to pick the suitable branch at compile time.

Quite similar to the solution found for binding Rec<GenNode> onto a typed Tuple
2018-04-09 02:19:54 +02:00
91b83f5ede ElementAccess: (WIP) unsuccessful attempt to solve the typing problem
the intention was to return disparate result types, just depending on the
actual position in the UI-Coordinates. The client knows what to expect
2018-04-09 01:14:12 +02:00
c245098d45 ElementAccess: (WIP) first draft for internal accessor function
...but can not work this way.
Since void* has not RTTI, no secure access with downcast is possible
2018-04-09 00:51:24 +02:00
20ecc3f0d0 DI: allow to trigger the lazy instantiation of a mock service instance directly
Basically the mocking mechanism just switches the configuration
and then waits for the service to be accessed in order to cause acutual
instantiation of the mock service implementation. But sometimes we want
to prepare and rig the mock instance prior to the first invocation;
in such cases it can be handy just to trigger the lazy creating process
2018-04-08 18:43:27 +02:00
ca9abaa9d9 ElementAccess: change wiring in ViewLocator into a dependency
...reduce immediate coupling, since we do not really now what actions ElementAccess
will actually perform, and this is likely to remain this way for some time.
So just let it sit there are an on-demand dependency.

Moreover, create an (empty placeholder) implementation within WindowLocator.
So everything is set now for the actual implementation to be filled in
2018-04-07 02:55:47 +02:00
09359cf92a ElementAccess: initial brainstorming about the interface mechanics 2018-04-07 02:28:29 +02:00
dc97ab5546 ElementAccess: consider helper to encapsulte access to actual GTK structures (#1134) 2018-04-07 01:00:25 +02:00
eae775b725 ViewSpec: rearrange dependencies to simplify testing
...but still not clear yet what we actually need to access from within the ViewSpecDSL_test
2018-04-05 22:23:34 +02:00
18a552002d ViewSpec: use mocked LocationSolver to verify operation of the DSL 2018-04-05 01:09:13 +02:00
64d5f868ea ViewSpec: and finally solve the daunting problem of service access
this is f***ng unbelievable.
Its just two lines of code now
VICTORY!
2018-04-04 04:37:13 +02:00
cb6155c85e ViewSpec: now turn the UILocationSolver into yet another global service
feels a bit uncanny after all
can't be *that* easy
2018-04-04 03:59:11 +02:00
4de2ea2abe ViewSpec: get rid of all the lambdas and global vars. LocationQuery is a service now
Harvesting the fruits of the DependencyFactory rework....
2018-04-04 03:48:53 +02:00
71bb2b48b6 ViewSpec: pick up with dependency-injection into the DSL tokens (#1126)
Attempt to find my way back to the point
where the digression regarding dependency-injection started.

As it turns out, this was a valuable digression, since we can rid ourselves
from lots of ad-hoc functionality, which basically does in a shitty way
what DependencyFactory now provides as standard solution


FIRST STEP is to expose the Navigator as generic "LocationQuery" service
through lib::Depend<LocationQuery>
2018-04-04 03:29:26 +02:00
6f2ed76d83 Improve the code for proxy generation
more of a layout improvement, to avoid any code duplication.
The mechanics remain the same
 - write an explicit specialisation
 - trigger template intantiation within a dedicated translation unit
2018-04-03 07:45:13 +02:00
db7172df29 DOC: update technical (doxygen) documentation to reflect the integration with lib::Depend 2018-04-03 06:37:36 +02:00
31a2e5879d Fix problem with ambiguous ctor overloads for DependInject::ServiceInstance
while switching various services to the new framework,
I noticed the requirement to create a service handle in not-yet-started mode
and then start it explicitly, maybe even from another thread. Thus I introduced
a no-arg default ctor for that purpose, but overlooked that the forwarding ctor
might also need zero arguments for default constructible service implementation
classes. Thus I've now introduced a marker ENUM for disambiguation
2018-04-03 05:15:33 +02:00
18d0970a86 Rework Interface-Proxy definition to fit with the new scheme
everything works now after the switch.
BUT this solution is ugly, we need to trigger template instantiation explicitly
2018-04-03 05:15:26 +02:00
f24c548443 Reorganise translation units for interface proxies
from now on, we'll have dedicated individual translation units (*cpp)
for each distinct interface proxy. All of these will include the
interfaceproxy.hpp, which now holds the boilerplate part of the code
and *must not be included* in anything else than interfac proxy
translation units. The reason is, we now *definie* (with external linkage)
implementations of the facade::Link ctor and dtor for each distinct
type of interface proxy. This allows to decouple the proxy definition code
from the service implementation code (which is crucial for plug-ins
like the GUI)
2018-04-03 03:14:55 +02:00
1101e1f1db Dismantle the woefully complex interfaceproxy Accessor in favour of lib::Depend
The recently rewritten lib::Depend front-end for service dependencies,
together with the configuration as lib::DependInject::ServiceInstance
provides all the necessary features and is even threadsafe.

Beyond that, the expectation is that also the instantiation of the
interface proxies can be simplified. The proxies themselves however
need to be hand-written as before
2018-04-03 02:44:12 +02:00
4e0d99e928 Demote the Play-Facade to a in-language (C++) Interface to get rid of InterfaceFacadeLink
I am fully aware this change has some far reaching ramifications.
Effectively I am hereby abandoning the goal of a highly modularised Lumiera,
where every major component is mapped over the Interface-System. This was
always a goal I accepted only reluctantly, and my now years of experience
confirm my reservation: it will cost us lots of efforts just for the
sake of being "sexy".
2018-04-03 02:14:45 +02:00
9f3c127240 (WIP) Draft to replace the Interface-Proxy-Binding by lib::Depend
in theory this should be possible and obsolete a lot of dedicated code,
since lib::Depend provides all the intance management and error checking
2018-04-02 08:20:56 +02:00
6fe8e970cb Switch further Service implementations and obsolete SingletonRef alltogether
SingletonRef was only invented because lib::Depend (or lib::Singleton at that time)
offered only on-demand initialisation, but could not attach to an external service.
But this is required for calling out at the implementation side of a
Lumiera Interface into the actual service implementation.

The recently created DependInject::ServiceInstance now fulfils this task way better
and is seamlessly integrated into the lib::Depend front-end
2018-04-02 05:00:01 +02:00
29ee5131f4 Switch first Layer-Separation-Interface to expose the service implementation via lib::Depend
Actually this is on the implementation side only.
Since Layer-Separation-Interfaces route each call through a binding layer,
we get two Service-"Instances" to manage
- on the client side we have to route into the Lumiera Interface system
- on the implementation side the C-Language calls from the Interface system
  need to get to the actual service implementation. The latter is now
  managed and exposed via DependInject::ServiceInstance
2018-04-02 04:19:17 +02:00
be789bea59 Fix funny problem with C header stdbool.h
...which is so kind as to redefine bool, true and false as macros. Yessss!
2018-04-02 03:27:07 +02:00
6460ff8344 Switch basic Application initialisation to the rewritten DependencyFactory
this is the classic case of a singleton object
2018-04-02 02:56:08 +02:00
4669260cd1 Fix setup of the ConfigManager implementation
...still using the FAKE implementation, not a real rules engine.
However, with the new Dependency-Injection framework we need to define
the actual class from the service-provider, not from some service-client.
This is more orthogonal, but we're forced to install a Lifecycle-Hook now,
in order to get this configuration into the system prior to any use
2018-04-02 02:20:54 +02:00
89d93a13e4 Modernise Unknown Exception handler and Exception messages 2018-04-02 01:48:51 +02:00
21e47e014a Modernise Lumiera Error baseclass 2018-04-01 23:45:00 +02:00
d6167c1845 DependencyFactory: reorder destructor to allow for re-entrance
This is borderline yet acceptable;
A service might indeed depend on itself circularly
The concrete example is the Advice-System, which needs to push
the clean-up of AdviceProvicions into a static context. From there
the deleters need to call back into the AdviceSystem, since they have
no wey to find out, if this is an individual Advice being retracted,
or a mass-cleanup due to system shutdown.

Thus the DependencyFactory now invokes the actual deleter
prior to setting the instance-Ptr to NULL.
This sidesteps the whole issue with the ClassLock, which actually
must be already destroyed at that point, according to the C++ standard.
(since it was created on-demand, on first actual usage, *after* the
DependencyFactory was statically initialised). A workaround would be
to have the ctor of DependencyFactory actively pull and allocate the
Monitor for the ClassLock; however this seems a bit overingeneered
to deal with such a borderline issue
2018-04-01 07:06:58 +02:00
bfbcc5de43 simplify ClassLock by use of Meyer's Singleton with zombie check
...and package the ZombieCheck as helper object.
Also rewrite the SyncClassLock_test to perform an
multithreaded contended test to prove the lock is shared and effective
2018-04-01 06:09:01 +02:00
21fdce0dfc a better solution to reject out-of-order static access after shutdown
Static initialisation and shutdown can be intricate; but in fact they
work quite precise and deterministic, once you understand the rules
of the game.

In the actual case at hand the ClassLock was already destroyed, and
it must be destroyed at that point, according to the standard. Simply
because it is created on-demand, *after* the initialisation of the
static DependencyFactory, which uses this lock, and so its destructor
must be called befor the dtor of DependencyFactory -- which is precisely
what happens.

So there is no need to establish a special secure "base runtime system",
and this whole idea is ill-guided. I'll thus close ticket #1133 as wontfix

Conflicts:
	src/lib/dependable-base.hpp
2018-04-01 04:52:50 +02:00
a8273283d1 (WIP) fruitless efforts to build a dependable static environment
My gut feeling tells me that I am on the wrong track alltogether
2018-04-01 04:52:01 +02:00
992056ea69 reduce include dependencies of DelStash
...get rid of some further Boost includes and remove unnecessary disable_if
2018-04-01 00:37:58 +02:00
f0eeafddaa Identified some problems regarding static destruction
When some dependency or singleton violates Lumiera's policy regarding destructors and shutdown,
we are unable to detect this violation reliably and produce a Fatal Error message.
This is due to lib::Depend's de-initialisating being itself tied to template generated
static variables, which unfortunately have a visibility scope beyond the translation unit
responsible for construction and clean-up.
2018-03-31 17:27:13 +02:00
fe10ab92dc DI: adjust codebase to the new DependInject configuration API 2018-03-31 01:06:10 +02:00
80207ea224 DI: (WIP) switch to totally rewritten new implementation of lib::Depend (#1086)
- state-of-the-art implementation of access with Double Checked Locking + Atomics
- improved design for configuration of dependencies. Now at the provider, not the consumer
- support for exposing services with a lifecycle through the lib::Depend<SRV> front-end
2018-03-31 01:06:06 +02:00
043dc948e3 DI: (WIP) prepare for switch to the new implementation (#1086) 2018-03-31 01:06:00 +02:00
562c14e15d DI: safer to make DependencyFactor noncopyable
...and to use a dedicated function for transferring the definition
2018-03-30 07:57:08 +02:00
cc46c5b04b DI: solve problem with leftover deleter in testmock. Unit test PASS 2018-03-30 07:42:53 +02:00
5d0c2b6d2c DI: special solution for singletons with private default ctor
...which declare DependencyFactory as friend.
Yes, we want to encourrage that usage pattern.

Problem is, std::is_constructible<X> gives a misleading result in that case.
We need to do the instantiation check within the scope of DependencyFactory
2018-03-30 06:48:34 +02:00
b3d18c1a74 DI: rework dependency-injection configuration in terms of the new DependencyFactory
why is this so damn hard to get right?
2018-03-30 05:56:53 +02:00
88e37d5681 DI: draft new version of the DependencyFactory
...this time to abstract out most of the low-level functionality from lib::Depend
2018-03-29 21:48:34 +02:00
5fc85df385 DI: inline into lib::Depend to obsolete InstanceHolder
but now we've got two factory functors.
So there is yet more potential for simplification & refactoring
2018-03-29 16:57:55 +02:00
c3e149028f DI: draft towards unified use of the singleton holder
ideally we want
 - just a plain unique_ptr
 - but with custom deleter delegating to lib::Depend
 - Depend can be made fried to support private ctor/dtor
 - reset the instance-ptr on deletion
 - always kill any instance
2018-03-28 03:27:05 +02:00
d6786870f3 DI: port the old Singleton unit tests
all these tests are ported by drop-in replacement
and should work afterwards exactly as before (and they do indeed)

A minor twist was spotted though (nice to have more unit tests indeed!):
Sometimes we want to pass a custom constructor *not* as modern-style lambda,
but rather as direct function reference, function pointer or even member
function pointer. However, we can not store those types into the closure
for later lazy invocation. This is basically the same twist I run into
yesterday, when modernising the thread-wrapper. And the solution is
similar. Our traits class _Fun<FUN> has a new typedef Functor
with a suitable functor type to be instantiated and copied. In case of
the Lambda this is the (anonymous) lamda class itself, but in case of
a function reference or pointer it is a std::function.
2018-03-26 07:54:16 +02:00
4d783770d0 Bugfix: CallQueue_test initialisation was not threadsafe (see also #1131)
...which showed up under high system load.
The initialisation of the member variables for the check sum
could be delayed while the corresponding thread was already running
2018-03-26 04:40:54 +02:00
f4195c102a DI: document relation to lifecylce and lifecycle events in general 2018-03-26 02:28:49 +02:00
942bad5d0a DI: document the reworked Singleton / Dependency-Factory
- polish the text in the TiddlyWiki
 - integrate some new pages in the published documentation
   Still mostly placeholder text with some indications
 - fill in the relevant sections in the overview document
 - adjust, expand and update the Doxygen comments

TODO: could convert the TiddlyWiki page to Asciidoc and
      publish it mostly as-is. Especially the nice benchmarks
      from yesterday :-D
2018-03-25 09:33:57 +02:00
d78211a9a1 DI: implement C++11 solution of Double-Checked-Locking with std::atomic + Mutex
This solution is considered correct by the experts.

Regarding the dependency-configuration part, we do not care too much about performance
and use the somewhat slower default memory ordering constraint
2018-03-24 11:02:44 +01:00