1/**
2 * The osthread module provides types used in threads modules.
3 *
4 * Copyright: Copyright Sean Kelly 2005 - 2012.
5 * License: Distributed under the
6 *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7 *    (See accompanying file LICENSE)
8 * Authors:   Sean Kelly, Walter Bright, Alex R��nne Petersen, Martin Nowak
9 * Source:    $(DRUNTIMESRC core/thread/osthread.d)
10 */
11
12module core.thread.threadgroup;
13
14import core.thread.osthread;
15
16
17/**
18 * This class is intended to simplify certain common programming techniques.
19 */
20class ThreadGroup
21{
22    /**
23     * Creates and starts a new Thread object that executes fn and adds it to
24     * the list of tracked threads.
25     *
26     * Params:
27     *  fn = The thread function.
28     *
29     * Returns:
30     *  A reference to the newly created thread.
31     */
32    final Thread create(void function() fn)
33    {
34        Thread t = new Thread(fn).start();
35
36        synchronized(this)
37        {
38            m_all[t] = t;
39        }
40        return t;
41    }
42
43
44    /**
45     * Creates and starts a new Thread object that executes dg and adds it to
46     * the list of tracked threads.
47     *
48     * Params:
49     *  dg = The thread function.
50     *
51     * Returns:
52     *  A reference to the newly created thread.
53     */
54    final Thread create(void delegate() dg)
55    {
56        Thread t = new Thread(dg).start();
57
58        synchronized(this)
59        {
60            m_all[t] = t;
61        }
62        return t;
63    }
64
65
66    /**
67     * Add t to the list of tracked threads if it is not already being tracked.
68     *
69     * Params:
70     *  t = The thread to add.
71     *
72     * In:
73     *  t must not be null.
74     */
75    final void add(Thread t)
76    in
77    {
78        assert(t);
79    }
80    do
81    {
82        synchronized(this)
83        {
84            m_all[t] = t;
85        }
86    }
87
88
89    /**
90     * Removes t from the list of tracked threads.  No operation will be
91     * performed if t is not currently being tracked by this object.
92     *
93     * Params:
94     *  t = The thread to remove.
95     *
96     * In:
97     *  t must not be null.
98     */
99    final void remove(Thread t)
100    in
101    {
102        assert(t);
103    }
104    do
105    {
106        synchronized(this)
107        {
108            m_all.remove(t);
109        }
110    }
111
112
113    /**
114     * Operates on all threads currently tracked by this object.
115     */
116    final int opApply(scope int delegate(ref Thread) dg)
117    {
118        synchronized(this)
119        {
120            int ret = 0;
121
122            // NOTE: This loop relies on the knowledge that m_all uses the
123            //       Thread object for both the key and the mapped value.
124            foreach (Thread t; m_all.keys)
125            {
126                ret = dg(t);
127                if (ret)
128                    break;
129            }
130            return ret;
131        }
132    }
133
134
135    /**
136     * Iteratively joins all tracked threads.  This function will block add,
137     * remove, and opApply until it completes.
138     *
139     * Params:
140     *  rethrow = Rethrow any unhandled exception which may have caused the
141     *            current thread to terminate.
142     *
143     * Throws:
144     *  Any exception not handled by the joined threads.
145     */
146    final void joinAll(bool rethrow = true)
147    {
148        synchronized(this)
149        {
150            // NOTE: This loop relies on the knowledge that m_all uses the
151            //       Thread object for both the key and the mapped value.
152            foreach (Thread t; m_all.keys)
153            {
154                t.join(rethrow);
155            }
156        }
157    }
158
159
160private:
161    Thread[Thread]  m_all;
162}
163