-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathproblem_gp_ub.tex
64 lines (53 loc) · 3.21 KB
/
problem_gp_ub.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
\abschnitt{problem: avoiding non-const global variables and
undefined behaviour}\label{problem_gpub}
According to \emph{C++ core guidelines}\cite{coreguidlines}, non-const global
variables should be avoided: they hide dependencies and make the
dependencies subject to unpredictable changes.
Global variables can be changed by assigning them indirectly using a pointer or
by a function call. As a consequence, the compiler can't cache the value of a
global variable in a register, degrading performance (unnecessary
loads and stores to global memory especially in performance critical loops).
Accessing a register is one to three orders of magnitude faster than accessing
memory (depending on whether the cache line is in cache and not invalidated by
another core; and depending on whether the page is in the TLB).
The order of initialisation (and thus destruction) of static global
variables is not defined, introducing additional problems with static
global variables.
\zs{A library designed to be used as building block by other higher-level
frameworks should avoid introducing global variables. If this API were
specified in terms of internal global variables, no higher level layer could undo
that: it would be stuck with the global variables.}
\uabschnitt{switch back to \emph{main()} by returning}
Switching back to \main by returning from the fiber function has two drawbacks:
it requires an internal global variable pointing to the suspended \main and
restricts the valid use cases.
\cppf{return_to_main}
For instance the generator pattern is impossible because the only way
for a fiber to transfer execution control back to \main is to terminate. But
this means that no way exists to transfer data (sequence of values) back and
forth between a fiber and \main.
\zs{Switching to \main only by returning is impractical because it limits the
applicability of fibers and requires an internal global variable pointing to
\main.}
\uabschnitt{static member function returns active \fiber}
P0099R0\cite{P0099R0} introduced a static member function\\
(\cpp{execution_context::current()}) that returned an instance of the active
fiber. This allows passing the active fiber \cpp{m} (for instance representing
\main) into the fiber \cpp{f} via lambda capture. This mechanism enables
switching back and forth between the fiber and \main, enabling a rich set of
applications (for instance generators).
\cppf{static_current}
But this solution requires an internal global variable pointing to the active
fiber and some kind of reference counting. Reference counting is needed because
\cpp{fiber\_context::current()} necessarily requires multiple instances of \fiber for the
active fiber. Only when the last reference goes out of scope can the fiber be
destroyed and its stack deallocated.
\cppf{multi_current}
Additionally a static member function returning an instance of the active fiber
would violate the protection requirements of sections \nameref{stackmgmt} and
\nameref{invalidation}. For instance you could accidentally attempt to resume
the active fiber by invoking \resume.
\cppf{resume_current}
\zs{A static member function returning the active fiber requires a reference
counted global variable and does not prevent accidentally attempting to resume
the active fiber.}