1 /*
2  * DSFML - The Simple and Fast Multimedia Library for D
3  *
4  * Copyright (c) 2013 - 2017 Jeremy DeHaan (dehaan.jeremiah@gmail.com)
5  *
6  * This software is provided 'as-is', without any express or implied warranty.
7  * In no event will the authors be held liable for any damages arising from the
8  * use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not claim
15  * that you wrote the original software. If you use this software in a product,
16  * an acknowledgment in the product documentation would be appreciated but is
17  * not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  * misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source distribution
23  */
24 
25 /**
26  * Threads provide a way to run multiple parts of the code in parallel. When you
27  * launch a new thread, the execution is split and both the new thread and the
28  * caller run in parallel.
29  *
30  * To use a $(U Thread), you construct it directly with the function to execute
31  * as the entry point of the thread. $(U Thread) has multiple template
32  * constructors, which means that you can use several types of entry points:
33  * $(UL
34  * $(LI functions with no arguments)
35  * $(LI delegates with no arguments))
36  *
37  * $(PARA
38  * The thread ends when its function is terminated. If the owner $(U Thread)
39  * instance is destroyed before the thread is finished, the destructor will wait
40  * (see `wait()`).)
41  *
42  * Example:
43  * ---
44  * // example 1: function
45  * void threadFunc()
46  * {
47  *   ...
48  * }
49  *
50  * auto thread = new Thread(&threadFunc);
51  * thread.launch();
52  *
53  * // example 2: delegate
54  * class Task
55  * {
56  *    void run()
57  *    {
58  *       ...
59  *    }
60  * }
61  *
62  * auto task = new Task();
63  * auto thread = new Thread(&task.run);
64  * thread.launch();
65  * ---
66  */
67 module dsfml.system.thread;
68 
69 import core = core.thread;
70 
71 /**
72  * Utility class to manipulate threads.
73  */
74 class Thread
75 {
76 	private core.Thread m_thread;
77 
78 	/**
79 	 * Construct the thread from a functor with no argument
80 	 *
81 	 * Params:
82 	 * 		fn  = The function to use as the entry point of the thread
83 	 * 		sz  = The size of the stack
84 	 */
85 	this(void function() fn, size_t sz = 0)
86 	{
87 		m_thread = new core.Thread(fn,sz);
88 	}
89 
90 	/**
91 	 * Construct the thread from a delegate with no argument
92 	 *
93 	 * Params:
94 	 * 		dg  = The delegate to use as the entry point of the thread
95 	 * 		sz  = The size of the stack
96 	 */
97 	this(void delegate() dg, size_t sz = 0)
98 	{
99 		m_thread = new core.Thread(dg, sz);
100 	}
101 
102 	/// Destructor
103 	~this()
104 	{
105 		import dsfml.system.config;
106 		mixin(destructorOutput);
107 	}
108 
109 	/// Run the thread.
110 	void launch()
111 	{
112 		m_thread.start();
113 	}
114 
115 	/// Wait until the thread finishes.
116 	void wait()
117 	{
118 		if(m_thread.isRunning())
119 		{
120 			m_thread.join(true);
121 		}
122 	}
123 
124 }
125 
126 unittest
127 {
128 	version(DSFML_Unittest_System)
129 	{
130 		import std.stdio;
131 		import dsfml.system.sleep;
132 		import core.time;
133 
134 
135 		void secondThreadHello()
136 		{
137 			for(int i = 0; i < 10; ++i)
138 			{
139 				writeln("Hello from the second thread!");
140 			}
141 		}
142 
143 
144 
145 
146 		writeln("Unit test for Thread class");
147 		writeln();
148 
149 		writeln("Running two functions at once.");
150 
151 		auto secondThread = new Thread(&secondThreadHello);
152 
153 
154 		secondThread.launch();
155 
156 		for(int i = 0; i < 10; ++i)
157 		{
158 			writeln("Hello from the main thread!");
159 		}
160 
161 		sleep(seconds(1));
162 
163 		//writeln("Letting a thread run completely before going back to the main thread.");
164 
165 		//secondThread = new Thread(&secondThreadHello);//To prevent threading errors, create a new thread before calling launch again
166 
167 		//secondThread.launch();
168 
169 		//secondThread.wait();
170 
171 		//for(int i = 0; i < 10; ++i)
172 		//{
173 		//	writeln("Hello from the main thread!");
174 		//}
175 	}
176 
177 }