|
2 | 2 | tracemultiplexer |
3 | 3 | ================ |
4 | 4 |
|
5 | | -This model simulates a multi-threaded program that has been |
6 | | -instrumented to save traces of its API calls in a log. |
| 5 | +Simulate a program where two threads write to the same log file. |
| 6 | +Investigate synchronization to ensure that only one thread at a |
| 7 | +time can write to the log. |
7 | 8 |
|
8 | | -When multiple threads are writing the trace log, there can be |
9 | | -nondeterminism in the order in which API calls and returns are made, and |
10 | | -the order they appear in the trace log. The purpose of this sample is |
11 | | -to demonstrate that nondeterminism. |
| 9 | +States where both threads may write to the log are considered unsafe |
| 10 | +states. Marked log messages may have been corrupted by unsynchronized |
| 11 | +writes from both threads. |
12 | 12 |
|
13 | 13 | More details appear in the *tracemultiplexer* comment header. |
14 | 14 |
|
15 | | -- *tracemultiplexer*: simulates a multi-threaded program that has been |
16 | | - instrumented to save traces of its API calls in a log. |
| 15 | +- *tracemultiplexer*: model program that simulates a multi-threaded |
| 16 | + program with and without synchronization. |
17 | 17 |
|
18 | | -- *test_graphics* - generate a graph that shows the behavior of *tracemultiplexer* |
| 18 | +- *test_viewer* - generate a graph that shows the behavior of |
| 19 | + *tracemultiplexer* using a lock to synchronize write access to the |
| 20 | + log file, and a second graph showing the behavior of |
| 21 | + *tracemultiplexer* with the *unsynchronized* configuration that |
| 22 | + ignores the lock. |
19 | 23 |
|
20 | | -- *fsmpy*, *svg* - directories of output from the test scripts |
| 24 | +- *fsmpy*, *svg* - directories of output from *test_viewer* |
21 | 25 |
|
22 | | -View the generated graphics file in a browser. Hover the |
23 | | -pointer over any state bubble to see a tooltip that shows the state |
24 | | -variables in that state. |
| 26 | +View the generated *.svg* files in a browser. Hover the pointer over |
| 27 | +any state bubble to see a tooltip that shows the state variables in |
| 28 | +that state. |
| 29 | + |
| 30 | +The *log* variable represents the log file: it is a list of tuples |
| 31 | +where each tuple represents a log message. Messages that end with |
| 32 | +*'XXX'* were logged when both threads may have written to the log, |
| 33 | +so the message may have been corrupted by unsynchronized writes. |
25 | 34 |
|
26 | 35 | - *tracemultiplexerFSM* - graph that shows the behavior of *tracemultiplexer* |
| 36 | + using the lock. None of the states in this graph are unsafe. None of the |
| 37 | + log messages are marked with *'XXX'*. |
| 38 | + |
| 39 | +- *unsynchronizedFSM* - graph that shows the behavior of *tracemultiplexer* |
| 40 | + ignoring the lock. There are many more transitions and states in this |
| 41 | + graph because the threads are unsynchronized, so many more interleavings are |
| 42 | + possible. There are many unsafe states (colored red) where both threads may |
| 43 | + write to the log. In every unsafe state, the most recently written message in |
| 44 | + *log* ends with *'XXX'* to indicate it may have been corrupted by |
| 45 | + unsynchronized writes. These corrupted messages persist in *log* in |
| 46 | + subsequent states. |
27 | 47 |
|
28 | 48 | There is no stepper in this sample. |
29 | 49 |
|
|
0 commit comments