OOSMOS Thread Example
1. Introduction
2. Thread on Various Platforms
2.1 Thread on PIC32
2.2 Thread on Windows
1. Introduction
2. Thread on Various Plat...
2.1 Thread on PIC32
2.2 Thread on Windows
1. Introduction
2. Thread on Various Pl...
2.1 Thread on PIC32
2.2 Thread on Windows
1. Introduction
2. Thread on Various ...
2.1 Thread on PIC32
2.2 Thread on Windows

1. Introduction

This is a comprehensive example of OOSMOS's 'state threads'. In order to include all the different thread call types, we use the threadtest class which tests them all.
Because Thread calls must be made from within an oosmos_POLL event and because the tests are granular, we test a little bit in each state. See Figure 1 that shows the state machine — a test per state.
Figure 1. threadtest State Chart
This is the threadtest source code:
1
22
23
24
25
26
27
28
29
30
[GPLv2]
 
#ifndef _threadtest_h
#define _threadtest_h
 
typedef struct threadtestTag threadtest;
 
extern threadtest * threadtestNew(void);
 
#endif
threadtest.h
1
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
57
58
59
60
61
62
63
64
65
66
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
465
466
467
468
469
470
471
472
488
489
490
491
[GPLv2]
 
#include "oosmos.h"
#include "prt.h"
#include "threadtest.h"
#include <stdlib.h>
#include <stdbool.h>
 
//
// Adjust this in order to preallocate all 'threadtest' objects.
// Use 1 for a memory constrained environment.
//
#ifndef MAX_THREADTEST
#define MAX_THREADTEST 10
#endif
 
//>>>EVENTS
[Code generated by OOSMOS]
//<<<EVENTS
 
typedef union {
oosmos_sEvent Base;
} uEvents;
 
struct threadtestTag
{
//>>>DECL
[Code generated by OOSMOS]
//<<<DECL
int m_WC_Timeout_Successes;
 
int m_WCT_Event_RightPath;
int m_WCT_Event_WrongPath;
 
int m_D_RightPath;
int m_D_WrongPath;
 
int m_E_RightPath;
int m_E_WrongPath;
 
int m_WE_Timeout_Successes;
 
int m_WET_Event_RightPath;
int m_WET_Event_WrongPath;
 
int m_WET_Exit_RightPath;
int m_WET_Exit_WrongPath;
};
 
static bool ConditionRandom(int Range)
{
return rand() % Range == 0;
}
 
static bool ConditionTrue(void)
{
return true;
}
 
static bool ConditionFalse(void)
{
return false;
}
 
static void DelayMS_Thread(threadtest * pThreadTest, oosmos_sState * pState)
{
oosmos_UNUSED(pThreadTest);
 
oosmos_ThreadBegin();
prtFormatted("ThreadDelayMS...\n");
oosmos_ThreadDelayMS(3000);
prtFormatted("ThreadDelayMS SUCCESS\n\n");
oosmos_ThreadEnd();
}
 
static void WaitCond_Thread(threadtest * pThreadTest, oosmos_sState * pState)
{
oosmos_ThreadBegin();
prtFormatted("ThreadWaitCond...\n");
oosmos_ThreadWaitCond(ConditionRandom(2));
prtFormatted("ThreadWaitCond SUCCESS\n\n");
oosmos_ThreadEnd();
}
 
static void WaitCond_TimeoutMS_Thread(threadtest * pThreadTest, oosmos_sState * pState)
{
oosmos_ThreadBegin();
bool TimedOut;
pThreadTest->m_WC_Timeout_Successes = 0;
 
prtFormatted("ThreadWaitCond_TimeoutMS...\n");
 
oosmos_ThreadWaitCond_TimeoutMS(ConditionTrue(), 100, &TimedOut);
pThreadTest->m_WC_Timeout_Successes += (TimedOut == false);
 
oosmos_ThreadWaitCond_TimeoutMS(ConditionFalse(), 100, &TimedOut);
pThreadTest->m_WC_Timeout_Successes += (TimedOut == true);
prtFormatted("ThreadWaitCond_TimeoutMS %s\n\n", pThreadTest->m_WC_Timeout_Successes == 2 ? "SUCCESS" : "FAILURE");
oosmos_ThreadEnd();
}
 
static void WaitCond_TimeoutMS_Event_Thread(threadtest * pThreadTest, oosmos_sState * pState)
{
oosmos_ThreadBegin();
pThreadTest->m_WCT_Event_RightPath = 0;
pThreadTest->m_WCT_Event_WrongPath = 0;
 
prtFormatted("ThreadWaitCond_TimeoutMS_Event...\n");
 
oosmos_ThreadWaitCond_TimeoutMS_Event(ConditionTrue(), 100, evTimedOut1);
pThreadTest->m_WCT_Event_RightPath += 1;
 
oosmos_ThreadWaitCond_TimeoutMS_Event(ConditionFalse(), 100, evTimedOut2);
pThreadTest->m_WCT_Event_WrongPath += 1;
oosmos_ThreadFinally();
prtFormatted("ThreadWaitCond_TimeoutMS_Event %s\n\n", pThreadTest->m_WCT_Event_RightPath == 2 && pThreadTest->m_WCT_Event_WrongPath == 0 ? "SUCCESS" : "FAILURE");
oosmos_ThreadEnd();
}
 
static void WaitCond_TimeoutMS_Exit_Thread(threadtest * pThreadTest, oosmos_sState * pState)
{
oosmos_ThreadBegin();
pThreadTest->m_D_RightPath = 0;
pThreadTest->m_D_WrongPath = 0;
 
prtFormatted("ThreadWaitCond_TimeoutMS_Exit...\n");
 
oosmos_ThreadWaitCond_TimeoutMS_Exit(ConditionTrue(), 100);
pThreadTest->m_D_RightPath += 1;
 
oosmos_ThreadWaitCond_TimeoutMS_Exit(ConditionFalse(), 100);
pThreadTest->m_D_WrongPath += 1;
 
oosmos_ThreadFinally();
pThreadTest->m_D_RightPath += 1;
prtFormatted("ThreadWaitCond_TimeoutMS_Exit %s\n\n", pThreadTest->m_D_RightPath == 2 && pThreadTest->m_D_WrongPath == 0 ? "SUCCESS" : "FAILURE");
oosmos_ThreadEnd();
}
 
static void WaitEvent_Thread(threadtest * pThreadTest, oosmos_sState * pState)
{
oosmos_ThreadBegin();
prtFormatted("ThreadWaitEvent...\n");
 
oosmos_PushEventCode(pThreadTest, evPrint);
oosmos_ThreadWaitEvent(evDone);
prtFormatted("ThreadWaitEvent SUCCESS\n\n");
oosmos_ThreadEnd();
}
 
static void WaitEvent_TimeoutMS_Thread(threadtest * pThreadTest, oosmos_sState * pState)
{
oosmos_ThreadBegin();
bool TimedOut;
pThreadTest->m_WE_Timeout_Successes = 0;
 
prtFormatted("ThreadWaitEvent_TimeoutMS...\n");
 
oosmos_PushEventCode(pThreadTest, evPrint);
oosmos_ThreadWaitEvent_TimeoutMS(ConditionTrue(), 100, &TimedOut);
pThreadTest->m_WE_Timeout_Successes += (TimedOut == false);
 
oosmos_ThreadWaitEvent_TimeoutMS(ConditionFalse(), 100, &TimedOut);
pThreadTest->m_WE_Timeout_Successes += (TimedOut == true);
prtFormatted("ThreadWaitEvent_TimeoutMS %s\n\n", pThreadTest->m_WE_Timeout_Successes == 2 ? "SUCCESS" : "FAILURE");
oosmos_ThreadEnd();
}
 
static void WaitEvent_TimeoutMS_Event_Thread(threadtest * pThreadTest, oosmos_sState * pState)
{
oosmos_ThreadBegin();
pThreadTest->m_WET_Event_RightPath = 0;
pThreadTest->m_WET_Event_WrongPath = 0;
 
prtFormatted("ThreadWaitEvent_TimeoutMS_Event...\n");
 
//
// Enqueue 'evPrint' to the orthogonal state. We expect to get an 'evDone' well
// before the timeout.
//
oosmos_PushEventCode(pThreadTest, evPrint);
oosmos_ThreadWaitEvent_TimeoutMS_Event(evDone, 100, evTimedOut1);
pThreadTest->m_WET_Event_RightPath += 1;
 
//
// We don't enqueue 'evPrint' so we don't expect an 'evDone' therefore it should time out.
//
oosmos_ThreadWaitEvent_TimeoutMS_Event(evDone, 100, evTimedOut2);
pThreadTest->m_WET_Event_WrongPath += 1;
oosmos_ThreadFinally();
prtFormatted("ThreadWaitEvent_TimeoutMS_Event %s\n\n", pThreadTest->m_WET_Event_RightPath == 2 && pThreadTest->m_WET_Event_WrongPath == 0 ? "SUCCESS" : "FAILURE");
oosmos_ThreadEnd();
}
 
static void WaitEvent_TimeoutMS_Exit_Thread(threadtest * pThreadTest, oosmos_sState * pState)
{
oosmos_ThreadBegin();
pThreadTest->m_WET_Exit_RightPath = 0;
pThreadTest->m_WET_Exit_WrongPath = 0;
 
prtFormatted("ThreadWaitEvent_TimeoutMS_Exit...\n");
 
//
// Enqueue 'evPrint' to the orthogonal state. We expect to get and 'evDone' well
// before the timeout.
//
oosmos_PushEventCode(pThreadTest, evPrint);
oosmos_ThreadWaitEvent_TimeoutMS_Exit(evDone, 100);
pThreadTest->m_WET_Exit_RightPath += 1;
 
//
// We don't enqueue 'evPrint' so we don't expect an 'evDone' therefore it should time out and exit.
//
oosmos_ThreadWaitEvent_TimeoutMS_Exit(evDone, 100);
pThreadTest->m_WET_Exit_WrongPath += 1;
 
oosmos_ThreadFinally();
pThreadTest->m_WET_Exit_RightPath += 1;
prtFormatted("ThreadWaitEvent_TimeoutMS_Exit %s\n\n", pThreadTest->m_WET_Exit_RightPath == 2 && pThreadTest->m_WET_Exit_WrongPath == 0 ? "SUCCESS" : "FAILURE");
exit(1);
oosmos_ThreadEnd();
}
 
//>>>CODE
[Code generated by OOSMOS]
//<<<CODE
 
extern threadtest * threadtestNew(void)
{
oosmos_Allocate(pThreadTest, threadtest, MAX_THREADTEST, NULL);
 
//>>>INIT
[Code generated by OOSMOS]
//<<<INIT
 
return pThreadTest;
}
threadtest.c

2. Thread on Various Platforms

The Thread example will run on any platform but we have only packaged the Examples directory with PIC32 and Windows implementations.

2.1 Thread on PIC32

1
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[GPLv2]
 
#include "oosmos.h"
#include "threadtest.h"
 
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
 
#define THREAD_TESTS 1
 
extern int main(void)
{
oosmos_ClockSpeedInMHz(80);
 
for (int I = 1; I <= THREAD_TESTS; I++) {
(void) threadtestNew();
}
 
for (;;) {
oosmos_RunStateMachines();
oosmos_DelayMS(1);
}
}
main.c - Thread for PIC32

2.2 Thread on Windows

On Windows, we create all the threadtest objects and then drop into the conventional Windows oosmos_RunStateMachines loop.
Change THREADTESTS to whatever you like but it's easier to step through with a source level debugger when it is set to 1.
1
22
23
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[GPLv2]
 
#includes...
 
#define THREAD_TESTS 1
 
extern int main(void)
{
for (int I = 1; I <= THREAD_TESTS; I++) {
(void) threadtestNew();
}
 
for (;;) {
oosmos_RunStateMachines();
oosmos_DelayMS(1);
}
}
main.c - Thread for Windows
Copyright © 2014-2019  OOSMOS, LLC