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" ]; }