morph
0.1.0
Asynchronous bridge between GUI thread and business models
Toggle main menu visibility
Loading...
Searching...
No Matches
owner_affinity.hpp
Go to the documentation of this file.
1
// SPDX-License-Identifier: Apache-2.0
2
3
#pragma once
4
#include <core/async/ExecutorContext.hpp>
5
#include <thread>
6
7
#include "../../attributes.hpp"
8
#include "../executor.hpp"
9
#include "
owner_probe.hpp
"
10
11
/// @file
12
/// @brief "Am I on my owner?" for a component that belongs to one executor.
13
///
14
/// Specified in `docs/spec/core/executor.md`, "Owner affinity".
15
16
namespace
morph::exec::detail {
17
18
/// @brief The owner a component belongs to, and the check each of its
19
/// owner-only bodies makes on entry.
20
///
21
/// A component is on its owner inside a task the owner runs (`runningOn`),
22
/// and — when it was constructed on a thread running no executor's task — on
23
/// that thread. The second half is what a GUI owner needs: its thread runs
24
/// code outside the owner's tasks too (a Qt slot, a QML handler, a test body,
25
/// `main()` before its event loop starts), and that code is the owner. A
26
/// component constructed inside an executor's task — on a pool or a strand —
27
/// records no thread and is checked by `runningOn` alone. Copying an affinity
28
/// hands a collaborator (the bridge's backend) the same answer.
29
class
OwnerAffinity {
30
public
:
31
/// @param owner The executor the component belongs to. Borrowed: it must
32
/// outlive the component.
33
explicit
OwnerAffinity(IExecutor& owner MORPH_LIFETIMEBOUND) noexcept
34
: _owner{&owner},
35
_thread{::core::async::ExecutorScope::innermost() ==
nullptr
? std::this_thread::get_id()
36
: std::thread::id{}} {}
37
38
/// @brief The owner.
39
/// @return The executor passed at construction.
40
[[nodiscard]] IExecutor& owner() const noexcept {
return
*_owner; }
41
42
/// @brief Whether the calling thread is on the owner.
43
/// @return True inside a task of the owner, or on the thread that
44
/// constructed this affinity outside every executor's task.
45
[[nodiscard]]
bool
here() const noexcept {
46
return
runningOn(*_owner) || (_thread != std::thread::id{} && std::this_thread::get_id() == _thread);
47
}
48
49
/// @brief Records that @p site is running a body that must run on the owner:
50
/// asserts in a debug build, or reports to an installed probe.
51
/// @param site A static string naming the body, e.g. `"Bridge::executeVia"`.
52
void
note(
char
const
* site)
const
noexcept
{ noteOwner(site, _owner->coreExecutor(), here()); }
53
54
private
:
55
IExecutor* _owner;
56
std::thread::id _thread;
57
};
58
59
}
// namespace morph::exec::detail
owner_probe.hpp
The check every loop-owned body makes on entry: "am I on my owner?".
morph
core
detail
owner_affinity.hpp
Generated by
1.17.0