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