digraph thread_states { | |
// States | |
alive; | |
running; | |
wait_mutex; | |
wait_condvar; | |
wait_join; | |
zombie; | |
dead; | |
// Legitimate transitions | |
alive -> running; | |
dead -> alive [ label="reused" ]; | |
running -> wait_join [ label="wait for another\nthread termination" ]; | |
wait_join -> running [ label="target thread\nterminates" ]; | |
running -> zombie [ label="non-detached thread\nterminates" ]; | |
zombie -> dead [ label="join completed" ]; | |
running -> dead [ label="detached thread\nterminates" ]; | |
running -> wait_mutex [ label="wait for mutex\nacquisition" ]; | |
wait_mutex -> running [ label="mutex\nacquired" ]; | |
wait_mutex -> running [ label="mutex\ngiven up" ]; | |
running -> wait_condvar [ label="wait for condition variable" ]; | |
wait_condvar -> running [ label="woken" ]; | |
// How to handle bad actions | |
wait_mutex -> zombie [ style=dotted, label="thread dies\nwaiting" ]; | |
wait_mutex -> dead [ style=dotted, label="thread dies\nwaiting" ]; | |
wait_mutex -> wait_condvar [ style=dotted, label="waiting for\nmultiple objects" ]; | |
wait_mutex -> wait_join [ style=dotted, label="waiting for\nmultiple objects" ]; | |
wait_condvar -> zombie [ style=dotted, label="thread dies\nwaiting" ]; | |
wait_condvar -> dead [ style=dotted, label="thread dies\nwaiting" ]; | |
wait_condvar -> wait_mutex [ style=dotted, label="waiting for\nmultiple objects" ]; | |
wait_condvar -> wait_join [ style=dotted, label="waiting for\nmultiple objects" ]; | |
wait_join -> zombie [ style=dotted, label="thread dies\nwaiting" ]; | |
wait_join -> dead [ style=dotted, label="thread dies\nwaiting" ]; | |
wait_join -> wait_condvar [ style=dotted, label="waiting for\nmultiple objects" ]; | |
wait_join -> wait_mutex [ style=dotted, label="waiting for\nmultiple objects" ]; | |
zombie -> running [ style=dotted, label="unholy\nresurrection" ]; | |
dead -> running [ style=dotted, label="unholy\nresurrection" ]; | |
} |