1digraph thread_states { 2 // States 3 alive; 4 running; 5 wait_mutex; 6 wait_condvar; 7 wait_join; 8 zombie; 9 dead; 10 11 // Legitimate transitions 12 alive -> running; 13 dead -> alive [ label="reused" ]; 14 15 running -> wait_join [ label="wait for another\nthread termination" ]; 16 wait_join -> running [ label="target thread\nterminates" ]; 17 18 running -> zombie [ label="non-detached thread\nterminates" ]; 19 zombie -> dead [ label="join completed" ]; 20 running -> dead [ label="detached thread\nterminates" ]; 21 22 running -> wait_mutex [ label="wait for mutex\nacquisition" ]; 23 wait_mutex -> running [ label="mutex\nacquired" ]; 24 wait_mutex -> running [ label="mutex\ngiven up" ]; 25 26 running -> wait_condvar [ label="wait for condition variable" ]; 27 wait_condvar -> running [ label="woken" ]; 28 29 // How to handle bad actions 30 wait_mutex -> zombie [ style=dotted, label="thread dies\nwaiting" ]; 31 wait_mutex -> dead [ style=dotted, label="thread dies\nwaiting" ]; 32 wait_mutex -> wait_condvar [ style=dotted, label="waiting for\nmultiple objects" ]; 33 wait_mutex -> wait_join [ style=dotted, label="waiting for\nmultiple objects" ]; 34 35 wait_condvar -> zombie [ style=dotted, label="thread dies\nwaiting" ]; 36 wait_condvar -> dead [ style=dotted, label="thread dies\nwaiting" ]; 37 wait_condvar -> wait_mutex [ style=dotted, label="waiting for\nmultiple objects" ]; 38 wait_condvar -> wait_join [ style=dotted, label="waiting for\nmultiple objects" ]; 39 40 wait_join -> zombie [ style=dotted, label="thread dies\nwaiting" ]; 41 wait_join -> dead [ style=dotted, label="thread dies\nwaiting" ]; 42 wait_join -> wait_condvar [ style=dotted, label="waiting for\nmultiple objects" ]; 43 wait_join -> wait_mutex [ style=dotted, label="waiting for\nmultiple objects" ]; 44 45 zombie -> running [ style=dotted, label="unholy\nresurrection" ]; 46 dead -> running [ style=dotted, label="unholy\nresurrection" ]; 47} 48