1 /**
2 This file provides `ScopedForeignCallback`, a RAII object
3 to be conventionally in every foreign callback.
4 
5 Copyright: Guillaume Piolat 2015-2023.
6 License:   http://www.boost.org/LICENSE_1_0.txt
7 */
8 module dplug.core.runtime;
9 
10 import dplug.core.fpcontrol;
11 
12 
13 /**
14     RAII struct to cover extern callbacks.
15     Nowadays it only deals with FPU/SSE control words
16     save/restore.
17 
18     When we used a D runtime, this used to manage thread
19     attachment and deattachment in each incoming exported
20     function.
21 
22     Calling this on callbacks is still mandatory, since
23     changing floating-point control work can happen and
24     create issues.
25 
26     Example:
27 
28         extern(C) myCallback()
29         {
30             ScopedForeignCallback!(false, true) cb;
31             cb.enter();
32 
33             // Rounding mode preserved here...
34         }
35 
36 */
37 struct ScopedForeignCallback(bool dummyDeprecated,
38                              bool saveRestoreFPU)
39 {
40 public:
41 nothrow:
42 @nogc:
43 
44     /// Call this in each callback.
45     void enter()
46     {
47         debug _entered = true;
48 
49         static if (saveRestoreFPU)
50             _fpControl.initialize();
51     }
52 
53     ~this()
54     {
55         // Ensure enter() was called.
56         debug assert(_entered);
57     }
58 
59     @disable this(this);
60 
61 private:
62 
63     static if (saveRestoreFPU)
64         FPControl _fpControl;
65 
66     debug bool _entered = false;
67 }
68 
69 
70