1
1
classdef stl < handle % #codegen
2
+ % STL simple thread library
3
+ %
4
+ % This class contains static-only methods that implement a simple thread interface
5
+ % for MATLAB Coder.
6
+ %
7
+ % Threads::
8
+ % launch create a thread
9
+ % cancel cancel a thread
10
+ % join wait for a thread to terminate
11
+ % sleep pause a thread
12
+ % self get thread id
13
+ %
14
+ % Mutexes:
15
+ % mutex create a mutex
16
+ % mutex_lock acquire lock on mutex
17
+ % mutex_try test a mutex
18
+ % mutex_unlock unlock a mutex
19
+ %
20
+ % Semaphores::
21
+ % semaphore create a semaphore
22
+ % semaphore_post post a semaphore
23
+ % semaphore_wait wait for a semaphore
24
+ % semaphore_try test a semaphore
25
+ % timer periodically post a semaphore
26
+ %
27
+ % Miscellaneous::
28
+ % log send a message to log stream
29
+ % argc get number of command line arguments
30
+ % argv get a command line argument
31
+ % copy copy a variable to thwart optimization
32
+ % debug enable debugging messages
33
+ %
34
+ % Copyright (C) 2018, by Peter I. Corke
2
35
3
36
methods (Static )
4
37
5
38
% command line arguments
6
39
function ac = argc()
40
+ % stl.argc Return number of command line arguments
41
+ %
42
+ % stl.argc is the number of command line arguments, and is always at least one.
43
+ %
44
+ % See also: stl.argv.
7
45
coder .cinclude(' stl.h' );
8
46
9
47
ac = int32(0 );
10
48
ac = coder .ceval(' stl_argc' ); % evaluate the C function
11
49
end
12
50
13
51
function s = argv(a )
52
+ % stl.argv Return command line argument
53
+ %
54
+ % S = stl.argv(I) is a character array representing the Ith command line argument.
55
+ %
56
+ % Notes::
57
+ % - I is in the range 0 to stl.argc-1.
58
+ % - I=0 returns the name of the command.
59
+ %
60
+ % See also: stl.argc.
14
61
coder .cinclude(' stl.h' );
15
62
16
63
s = ' ' ;
31
78
end
32
79
end
33
80
81
+ function debug(v )
82
+ % stl.debug Control debugging
83
+ %
84
+ % stl.debug(D) controls the display of debug messages. If D is true messages
85
+ % are enabled.
86
+ %
87
+ % See also: stl.log.
88
+ coder .ceval(' stl_debug' , v );
89
+ end
90
+
91
+ function v2 = copy(v )
92
+ % stl.copy Circumvent code optimization
93
+ %
94
+ % y = stl.copy(x) makes a copy y = x in such
95
+ v2 = v ;
96
+ coder .ceval(' stl_require' , coder .ref(v2 ));
97
+ end
98
+
34
99
% thread
35
- function tid = launch(name , arg )
100
+ function tid = launch(name , arg , stackdata )
101
+ % stl.launch Create a new thread
102
+ %
103
+ % tid = stl.launch(name) is the integer id of a new thread called name, which executes the
104
+ % MATLAB entry point name.
105
+ %
106
+ % tid = stl.launch(name, arg) as above but passes by reference the struct arg as an
107
+ % argument to the thread. Values in the struct can be shared by the caller and the thread.
108
+ %
109
+ % tid = stl.launch(name, arg, hasstackdata) as above but the logical hasstackdata indicates
110
+ % whether the MATLAB entry point requires passed stack data.
111
+ %
112
+ % Notes::
113
+ % - The thread id is a small integer which indexes into an internal thread table. If an error
114
+ % is obtained about too few threads then increase NTHREADS in stl.c and recompile.
115
+ % - If a struct is shared between threads then access should be controlled using a mutex. The
116
+ % most convenient way to do this is for the struct to contain a mutex id and the main thread
117
+ % to allocate a mutex.
118
+ % - The only way to tell if a thread has stack data is to look at the generated .c or .h file.
119
+ % If the function has 2 arguments then hasstackdata should be true.
120
+ %
121
+ % See also: stl.cancel, stl.join, stl.mutex, stl.copy.
36
122
coder .cinclude(' stl.h' );
37
123
38
124
if nargin < 2
39
125
arg = 0 ;
40
126
end
127
+ if nargin < 3
128
+ stackdata = 0 ;
129
+ end
41
130
tid = int32(0 );
42
- tid = coder .ceval(' stl_thread_create' , cstring(name ), coder .ref(arg ), int32( 0 ) ); % evaluate the C function
131
+ tid = coder .ceval(' stl_thread_create' , cstring(name ), coder .ref(arg ), stackdata ); % evaluate the C function
43
132
end
44
133
45
134
function cancel(id )
135
+ % stl.cancel Cancel a thread
136
+ %
137
+ % stl.cancel(tid) cancels the thread with the specified id.
138
+ %
139
+ % See also: stl.launch.
46
140
coder .cinclude(' stl.h' );
47
141
48
142
coder .ceval(' stl_thread_cancel' , id ) ; % evaluate the C function
49
143
end
50
144
51
145
function join(id )
146
+ % stl.join Wait for thread to exit
147
+ %
148
+ % stl.join(tid) waits until the thread with the specified id terminates.
149
+ %
150
+ % See also: stl.launch.
52
151
coder .cinclude(' stl.h' );
53
152
54
153
coder .ceval(' stl_thread_join' , id ) ; % evaluate the C function
55
154
end
56
155
57
156
function sleep(t )
157
+ % stl.sleep Pause this thread
158
+ %
159
+ % stl.sleep(D) pauses the current thread for the specified time D.
160
+ %
161
+ % Notes::
162
+ % - D does not have to be integer.
163
+ % - Precision ultimately depends on the system clock.
164
+ %
165
+ % See also: stl.timer.
58
166
coder .cinclude(' stl.h' );
59
167
coder .ceval(' stl_sleep' , t ); % evaluate the C function
60
168
end
61
169
62
170
function id = self()
171
+ % stl.self Get thread id
172
+ %
173
+ % tid = stl.self() is the id of the current thread.
174
+ %
175
+ % See also: stl.launch.
63
176
coder .cinclude(' stl.h' );
64
177
65
178
id = int32(0 );
66
179
id = coder .ceval(' stl_thread_self' ); % evaluate the C function
67
180
end
68
181
69
182
% mutex
70
- function mutex(name )
71
- coder .ceval(' stl_launch' , [name 0 ]); % evaluate the C function
183
+ function id = mutex(name )
184
+ % stl.mutex Create a mutex
185
+ %
186
+ % mid = stl.mutex(name) returns the id of a new mutex with the specified name.
187
+ %
188
+ % Notes::
189
+ % - The mutex is initially unlocked.
190
+ % - The mutex id is a small integer which indexes into an internal mutex table. If an error
191
+ % is obtained about too few mutexes then increase NMUTEXS in stl.c and recompile.
192
+ %
193
+ % See also: stl.mutex_lock, stl.mutex_try, stl.mutex_unlock.
194
+
195
+ id = int32(0 );
196
+ id = coder .ceval(' stl_mutex_create' , cstring(name )); % evaluate the C function
197
+ end
198
+
199
+ function mutex_lock(id )
200
+ % stl.mutex_lock Lock the mutex
201
+ %
202
+ % stl.mutex(mid) waits indefinitely until it can obtain a lock on the specified mutex.
203
+ %
204
+ % See also: stl.mutex_unlock, stl.mutex_try.
205
+ coder .ceval(' stl_mutex_lock' , id ); % evaluate the C function
206
+ end
207
+
208
+ function mutex_try(id )
209
+ % stl.mutex_try Test the mutex
210
+ %
211
+ % v = stl.mutex_try(mid) returns the mutex state: false if it is currently
212
+ % locked by another thread, or true if a lock on the mutex was obtained. It never blocks.
213
+ %
214
+ % See also: stl.mutex_unlock, stl.mutex.
215
+ coder .ceval(' stl_mutex_lock_noblock' , id ); % evaluate the C function
216
+ end
217
+
218
+ function mutex_unlock(id )
219
+ % stl.mutex_unlock Unlock the mutex
220
+ %
221
+ % stl.mutex_unlock(mid) unlocks the specified mutex. It never blocks.
222
+ %
223
+ % See also: stl.mutex, stl.mutex_try.
224
+ coder .ceval(' stl_mutex_unlock' , id ); % evaluate the C function
72
225
end
73
226
74
227
% semaphore
75
- function sid = semaphore(name )
228
+ function id = semaphore(name )
229
+ % stl.semaphore Create a semaphore
230
+ %
231
+ % sid = stl.semaphore(name) returns the id of a new semaphore with the specified name.
232
+ %
233
+ % Notes::
234
+ % - The semaphore is initially not raised/posted.
235
+ % - The semaphore id is a small integer which indexes into an internal semaphore table. If an error
236
+ % is obtained about too few semaphores then increase NSEMAPHORES in stl.c and recompile.
237
+ %
238
+ % See also: stl.semaphore_post, stl.semaphore_wait, stl.semaphore_try.
239
+
76
240
coder .cinclude(' stl.h' );
77
241
78
- sid = int32(0 );
79
- sid = coder .ceval(' stl_sem_create' , cstring(name )); % evaluate the C function
242
+ id = int32(0 );
243
+ id = coder .ceval(' stl_sem_create' , cstring(name )); % evaluate the C function
80
244
end
81
245
82
- function sempost(id )
246
+ function semaphore_post(id )
247
+ % stl.semaphore_post Post a semaphore
248
+ %
249
+ % stl.semaphore_post(sid) posts (raises) the specified semaphore.
250
+ %
251
+ % Notes::
252
+ % - Only one of the threads waiting on the semaphore will be unblocked.
253
+ %
254
+ % See also: stl.semaphore_wait, stl.semaphore_try.
83
255
coder .cinclude(' stl.h' );
84
256
85
257
coder .ceval(' stl_sem_post' , id ); % evaluate the C function
86
258
end
87
259
88
- function semwait(id , wait )
260
+ function semaphore_wait(id )
261
+ % stl.semaphore_wait Wait for a semaphore
262
+ %
263
+ % stl.semaphore_wait(sid) waits indefinitely until the specified semaphore is raised.
264
+ %
265
+ % See also: stl.semaphore_post, stl.semaphore_try.
266
+ coder .cinclude(' stl.h' );
267
+
268
+ coder .ceval(' stl_sem_wait' , id ); % evaluate the C function
269
+ end
270
+
271
+ function semaphore_try(id )
272
+ % stl.semaphore_try Test a semaphore
273
+ %
274
+ % v = stl.semaphore_try(sid) returns without blocking the semaphore status: true if raised, otherwise false.
275
+ %
276
+ % See also: stl.semaphore_post, stl.semaphore_wait.
89
277
coder .cinclude(' stl.h' );
90
278
91
279
if nargin < 2
92
280
wait = int32(0 );
93
281
end
94
- coder .ceval(' stl_sem_wait ' , id , wait ); % evaluate the C function
282
+ coder .ceval(' stl_sem_wait_noblock ' , id ); % evaluate the C function
95
283
end
96
284
97
285
% timer
98
286
function tmid = timer(name , interval , semid )
287
+ % stl.timer Create periodic timer
288
+ %
289
+ % tid = stl.timer(name, interval, semid) is the id of the timer that fires every interval seconds and
290
+ % raises the specified semaphore.
291
+ %
292
+ % Notes::
293
+ % - The interval is a float.
294
+ % - The first semaphore raise happens at time interval after the call.
295
+ % - The timer id is a small integer which indexes into an internal timer table. If an error
296
+ % is obtained about too few timers then increase NTIMERS in stl.c and recompile.
297
+ %
298
+ % See also: stl.semaphore_wait, stl.semaphore_try.
99
299
coder .cinclude(' stl.h' );
100
300
101
301
tmid = int32(0 );
@@ -111,6 +311,8 @@ function log(varargin)
111
311
%
112
312
% NOTES::
113
313
% - String arguments, not the format string, must be wrapped with cstring, eg. cstring('hello')
314
+ %
315
+ % See also: stl.debug.
114
316
coder .cinclude(' stl.h' );
115
317
116
318
coder .ceval(' stl_log' , cstring(varargin{1 }), varargin{2 : end } ); % evaluate the C function
0 commit comments