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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//! WSTP environment object management.
//!
//! It's necessary that a `WSENV` always outlive any links which are created in
//! that environment. However, requiring that every [`Link`][crate::Link] be tied
//! to the lifetime of a [`WstpEnv`] created by the user would make the `wstp` API
//! unnecessarily burdensome. The easiest way to manage this is to have a single,
//! global, shared environment instance, and use that internally in every `wstp`
//! wrapper API. (This is what [`stdenv`](https://reference.wolfram.com/language/ref/c/stdenv.html)
//! accomplishes for programs prepared with [`wsprep`](https://reference.wolfram.com/language/ref/program/wsprep.html)).
//!
//! In general, the existence of an explicit, shared WSTP environment object is a bit of
//! an anachronism -- ideally it wouldn't exist at all. Much of what `WSENV` contains is
//! effectively global state (e.g. signal handlers), which might better be represented as
//! hidden global variables in the WSTP C library. Where possible, `wstp` should avoid
//! exposing this detail of the WSTP C API.
//!
//! # Safety
//!
//! If the determination is made in the future to expose [`WstpEnv`] publically from `wstp`,
//! some safety conditions will need to be satisfied:
//!
//! * A [`Link`][crate::Link] MUST NOT be able to outlive the `WstpEnv` that its
//! creation was associated with.
//! * All [`Link`][crate::Link]'s MUST be closed before the `WstpEnv` they are
//! associated with is deinitialized (essentially a restatement of the first condition).
use Mutex;
use crate::;
/// The standard WSTP environment object.
///
/// *WSTP C API Documentation:* [`stdenv`](https://reference.wolfram.com/language/ref/c/stdenv.html)
static STDENV: = new;
/// Private. A WSTP library environment.
///
/// NOTE: This function should remain private. See note on [`crate::env`].
///
/// See [`initialize()`].
///
/// *WSTP C API Documentation:* [`WSENV`](https://reference.wolfram.com/language/ref/c/WSENV.html).
pub
/// FIXME: This is only valid for [`STDENV`] because we enforce exclusive access
/// via [`with_raw_stdenv()`]. Other general instances of `WstpEnv`
/// are not safe to send between threads. Use ForceSend?
unsafe
/// Enforce unique access to the raw `STDENV` value.
///
/// This prevents trying to create links stored on the same global `WSENV`
/// instance in multiple threads at the same time. The `WSENV` type and WSTP API
/// functions do not otherwise do synchronization when mutating `WSENV` instances.
pub
/// Deinitialize the [`WSENV`] static maintained by this library.
///
/// Ideally, this function would not be necessary. However, the WSTP C library internally
/// launches several background threads necessary for its operation. If these threads are
/// still running when the main() function returns, an ungraceful shutdown can occur, with
/// error messages being printed. This function is an escape hatch to permit users of this
/// library to ensure that all background thread shutdown before `main()` returns.
///
/// TODO: Make this function obsolete, either by changing the WSTP C library
/// implementation, or, perhaps easier, maintain a reference count of the number of
/// [`Link`] objects that have been created, and (re-)initialize and deinitialize
/// the `WSENV` static whenever that count rises from or falls to 0.
///
/// # Safety
///
/// All [`Link`] objects created by this library are associated with the global [`WSENV`]
/// static used internally. Deinitializing the global `WSENV` before all [`Link`] objects
/// have been dropped is not legal. Only call this function after ensuring that all
/// [`Link`] objects created by your code have been dropped.
pub unsafe