1 /*
2 * thread.cxx
3 *
4 * Sample program to test PWLib threads.
5 *
6 * Portable Windows Library
7 *
8 * Copyright (c) 2001,2002 Roger Hardiman
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is Roger Hardiman
23 *
24 * $Revision: 20385 $
25 * $Author: rjongbloed $
26 * $Date: 2008-06-04 05:40:38 -0500 (Wed, 04 Jun 2008) $
27 */
28
29 /*
30 * This sample program tests threads is PWLib. It creates two threads,
31 * one which display the number '1' and one which displays the number '2'.
32 * It also demonstrates starting a thread with Resume(), using
33 * Suspend() and Resume() to suspend a running thread and two different
34 * ways to make a thread terminate.
35 */
36
37 #include <ptlib.h>
38 #include <ptlib/pprocess.h>
39
40 /*
41 * Thread #1 displays the number 1 every 10ms.
42 * When it is created, Main() starts executing immediatly.
43 * The thread is terminated by calling Stop() which uses a PSyncPoint with a
44 * 10ms timeout.
45 */
46 class MyThread1 : public PThread
47 {
48 PCLASSINFO(MyThread1, PThread);
49 public:
MyThread1()50 MyThread1() : PThread(1000,NoAutoDeleteThread)
51 {
52 Resume(); // start running this thread when it is created.
53 }
54
Main()55 void Main() {
56 while (!shutdown.Wait(10)) { // 10ms delay
57 printf("1 ");
58 fflush(stdout);
59 Sleep(10);
60 }
61 }
62
Stop()63 void Stop() {
64 // signal the shutdown PSyncPoint. On the next iteration, the thread's
65 // Main() function will exit cleanly.
66 shutdown.Signal();
67 }
68
69 protected:
70 PSyncPoint shutdown;
71 };
72
73
74 /*
75 * Thread #2 displays the number 2 every 10 ms.
76 * This thread will not start automatically. We must call
77 * Resume() after creating the thread.
78 * The thread is terminated by calling Stop() which sets a local variable.
79 */
80 class MyThread2 : public PThread
81 {
82 PCLASSINFO(MyThread2, PThread);
83 public:
MyThread2()84 MyThread2() : PThread(1000,NoAutoDeleteThread) {
85 exitFlag = PFalse;
86 }
87
Main()88 void Main() {
89 while (1) {
90 // Check if we need to exit
91 exitMutex.Wait();
92 if (exitFlag == PTrue) {
93 exitMutex.Signal();
94 break;
95 }
96 exitMutex.Signal();
97
98 // Display the number 2, then sleep for a short time
99 printf("2 "); fflush(stdout);
100 Sleep(10); // sleep 10ms
101 }
102 }
103
Stop()104 void Stop() {
105 // set the exit flag. On the next iteration, the thread's
106 // Main() function will exit cleanly.
107 exitMutex.Wait();
108 exitFlag = PTrue;
109 exitMutex.Signal();
110 }
111
112 protected:
113 PMutex exitMutex;
114 PBoolean exitFlag;
115 };
116
117
118 /*
119 * The main program class
120 */
121 class ThreadTest : public PProcess
122 {
123 PCLASSINFO(ThreadTest, PProcess)
124 public:
125 void Main();
126 };
127
128 PCREATE_PROCESS(ThreadTest);
129
130 // The main program
Main()131 void ThreadTest::Main()
132 {
133 cout << "Thread Test Program" << endl;
134 cout << "This program will display the following:" << endl;
135 cout << " 2 seconds of 1 1 1 1 1..." << endl;
136 cout << " followed by 2 seconds of 1 2 1 2 1 2 1 2 1 2..." << endl;
137 cout << " followed by 2 seconds of 2 2 2 2 2..." << endl;
138 cout << " followed by 2 seconds of 1 2 1 2 1 2 1 2 1 2..." << endl;
139 cout << endl;
140 cout << "It tests thread creation, suspend and resume functions." << endl;
141 cout << endl;
142
143 // Create the threads
144 MyThread1 * mythread1;
145 MyThread2 * mythread2;
146
147 mythread1 = new MyThread1();
148 mythread2 = new MyThread2();
149
150
151 // Thread 1 should now be running, as there is a Resume() function
152 // in the thread constructor.
153 // Thread 2 should be suspended.
154 // Sleep for three seconds. Only thread 1 will be running.
155 // Display will show "1 1 1 1 1 1 1..."
156 sleep(2);
157
158
159 // Start the second thread.
160 // Both threads should be running
161 // Sleep for 3 seconds, allowing the threads to run.
162 // Display will show "1 2 1 2 1 2 1 2 1 2..."
163 mythread2->Resume();
164 sleep(2);
165
166
167 // Suspend thread 1.
168 // Sleep for 3 seconds. Only thread 2 should be running.
169 // Display will show "2 2 2 2 2 2 2..."
170 mythread1->Suspend();
171 sleep(2);
172
173
174 // Resume thread 1.
175 // Sleep for 3 seconds. Both threads should be running.
176 // Display will show "1 2 1 2 1 2 1 2 1 2..."
177 mythread1->Resume();
178 sleep(2);
179
180
181 // Clean up
182 mythread1->Stop();
183 mythread1->WaitForTermination();
184 cout << "Thread 1 terminated" << endl;
185
186 mythread2->Stop();
187 mythread2->WaitForTermination();
188 cout << "Thread 2 terminated" << endl;
189
190 delete mythread1;
191 delete mythread2;
192
193 }
194
195