xpcom/tests/TestThreads.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:c422c247561e
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "nsThreadUtils.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "nspr.h"
10 #include "nsCOMPtr.h"
11 #include "nsIServiceManager.h"
12 #include "nsXPCOM.h"
13
14 class nsRunner : public nsIRunnable {
15 public:
16 NS_DECL_THREADSAFE_ISUPPORTS
17
18 NS_IMETHOD Run() {
19 nsCOMPtr<nsIThread> thread;
20 nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread));
21 if (NS_FAILED(rv)) {
22 printf("failed to get current thread\n");
23 return rv;
24 }
25 printf("running %d on thread %p\n", mNum, (void *)thread.get());
26
27 // if we don't do something slow, we'll never see the other
28 // worker threads run
29 PR_Sleep(PR_MillisecondsToInterval(100));
30
31 return rv;
32 }
33
34 nsRunner(int num) : mNum(num) {
35 }
36
37 protected:
38 int mNum;
39 };
40
41 NS_IMPL_ISUPPORTS(nsRunner, nsIRunnable)
42
43 nsresult
44 TestThreads()
45 {
46 nsresult rv;
47
48 nsCOMPtr<nsIRunnable> event = new nsRunner(0);
49 if (!event)
50 return NS_ERROR_OUT_OF_MEMORY;
51
52 nsCOMPtr<nsIThread> runner;
53 rv = NS_NewThread(getter_AddRefs(runner), event);
54 if (NS_FAILED(rv)) {
55 printf("failed to create thread\n");
56 return rv;
57 }
58
59 nsCOMPtr<nsIThread> thread;
60 rv = NS_GetCurrentThread(getter_AddRefs(thread));
61 if (NS_FAILED(rv)) {
62 printf("failed to get current thread\n");
63 return rv;
64 }
65
66 rv = runner->Shutdown(); // wait for the runner to die before quitting
67 if (NS_FAILED(rv)) {
68 printf("join failed\n");
69 }
70
71 PR_Sleep(PR_MillisecondsToInterval(100)); // hopefully the runner will quit here
72
73 return NS_OK;
74 }
75
76 class nsStressRunner : public nsIRunnable {
77 public:
78 NS_DECL_THREADSAFE_ISUPPORTS
79
80 NS_IMETHOD Run() {
81 NS_ASSERTION(!mWasRun, "run twice!");
82 mWasRun = true;
83 PR_Sleep(1);
84 if (!PR_AtomicDecrement(&gNum)) {
85 printf(" last thread was %d\n", mNum);
86 }
87 return NS_OK;
88 }
89
90 nsStressRunner(int num) : mNum(num), mWasRun(false) {
91 PR_AtomicIncrement(&gNum);
92 }
93
94 static int32_t GetGlobalCount() {return gNum;}
95
96 private:
97 ~nsStressRunner() {
98 NS_ASSERTION(mWasRun, "never run!");
99 }
100
101 protected:
102 static int32_t gNum;
103 int32_t mNum;
104 bool mWasRun;
105 };
106
107 int32_t nsStressRunner::gNum = 0;
108
109 NS_IMPL_ISUPPORTS(nsStressRunner, nsIRunnable)
110
111 static int Stress(int loops, int threads)
112 {
113
114 for (int i = 0; i < loops; i++) {
115 printf("Loop %d of %d\n", i+1, loops);
116
117 int k;
118 nsIThread** array = new nsIThread*[threads];
119 NS_ASSERTION(array, "out of memory");
120
121 NS_ASSERTION(!nsStressRunner::GetGlobalCount(), "bad count of runnables");
122
123 for (k = 0; k < threads; k++) {
124 nsCOMPtr<nsIThread> t;
125 nsresult rv = NS_NewThread(getter_AddRefs(t), new nsStressRunner(k));
126 if (NS_FAILED(rv)) {
127 NS_ERROR("can't create thread");
128 return -1;
129 }
130 NS_ADDREF(array[k] = t);
131 }
132
133 for (k = threads-1; k >= 0; k--) {
134 array[k]->Shutdown();
135 NS_RELEASE(array[k]);
136 }
137 delete [] array;
138 }
139 return 0;
140 }
141
142 static void threadProc(void *arg)
143 {
144 // printf(" running thread %d\n", (int) arg);
145 PR_Sleep(1);
146 PR_ASSERT(PR_JOINABLE_THREAD == PR_GetThreadState(PR_GetCurrentThread()));
147 }
148
149 static int StressNSPR(int loops, int threads)
150 {
151
152 for (int i = 0; i < loops; i++) {
153 printf("Loop %d of %d\n", i+1, loops);
154
155 int k;
156 PRThread** array = new PRThread*[threads];
157 PR_ASSERT(array);
158
159 for (k = 0; k < threads; k++) {
160 array[k] = PR_CreateThread(PR_USER_THREAD,
161 threadProc, (void*) k,
162 PR_PRIORITY_NORMAL,
163 PR_GLOBAL_THREAD,
164 PR_JOINABLE_THREAD,
165 0);
166 PR_ASSERT(array[k]);
167 }
168
169 for (k = 0; k < threads; k++) {
170 PR_ASSERT(PR_JOINABLE_THREAD == PR_GetThreadState(array[k]));
171 }
172
173 for (k = threads-1; k >= 0; k--) {
174 PR_JoinThread(array[k]);
175 }
176 delete [] array;
177 }
178 return 0;
179 }
180
181
182 int
183 main(int argc, char** argv)
184 {
185 int retval = 0;
186 nsresult rv;
187
188 rv = NS_InitXPCOM2(nullptr, nullptr, nullptr);
189 if (NS_FAILED(rv)) return -1;
190
191 if (argc > 1 && !strcmp(argv[1], "-stress")) {
192 int loops;
193 int threads;
194 if (argc != 4 || *argv[2] != '-' || *argv[3] != '-' ||
195 !(loops = atoi(argv[2]+1)) || !(threads = atoi(argv[3]+1))) {
196 printf("To use -stress you must pass loop count and thread count...\n"
197 " TestThreads -stress -1000 -50\n");
198 } else {
199 printf("Running stress test with %d loops of %d threads each\n",
200 loops, threads);
201 retval = Stress(loops, threads);
202 }
203 } else if (argc > 1 && !strcmp(argv[1], "-stress-nspr")) {
204 int loops;
205 int threads;
206 if (argc != 4 || *argv[2] != '-' || *argv[3] != '-' ||
207 !(loops = atoi(argv[2]+1)) || !(threads = atoi(argv[3]+1))) {
208 printf("To use -stress-nspr you must pass loop count and thread count...\n"
209 " TestThreads -stress -1000 -50\n");
210 } else {
211 printf("Running stress test with %d loops of %d threads each\n",
212 loops, threads);
213 retval = StressNSPR(loops, threads);
214 }
215 } else {
216 rv = TestThreads();
217 if (NS_FAILED(rv)) return -1;
218 }
219
220 rv = NS_ShutdownXPCOM(nullptr);
221 if (NS_FAILED(rv)) return -1;
222 return retval;
223 }

mercurial