1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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/. */
8 ** Description: Exercising the thread private data bailywick.
22 class MyThread: public RCThread
33 ** class MyPrivateData
35 class MyPrivateData: public RCThreadPrivateData
38 virtual ~MyPrivateData();
42 MyPrivateData(const MyPrivateData&);
48 }; /* MyPrivateData */
50 static PRUintn key[128];
51 static PRIntn debug = 0;
52 static PRBool failed = PR_FALSE;
53 static PRBool should = PR_TRUE;
54 static PRBool did = PR_TRUE;
55 static PRFileDesc *fout = NULL;
57 static void PrintProgress(PRIntn line)
59 failed = failed || (should && !did);
60 failed = failed || (!should && did);
64 fout, "@ line %d destructor should %shave been called and was%s\n",
65 line, ((should) ? "" : "NOT "), ((did) ? "" : " NOT"));
69 static void MyAssert(const char *expr, const char *file, PRIntn line)
72 (void)PR_fprintf(fout, "'%s' in file: %s: %d\n", expr, file, line);
75 #define MY_ASSERT(_expr) \
76 ((_expr)?((void)0):MyAssert(# _expr,__FILE__,__LINE__))
78 int main(PRIntn argc, char *argv[])
83 const RCThreadPrivateData *pd;
85 PLOptState *opt = PL_CreateOptState(argc, argv, "d");
86 RCThread *primordial = RCThread::WrapPrimordialThread();
87 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
89 if (PL_OPT_BAD == os) continue;
92 case 'd': /* debug mode */
99 PL_DestroyOptState(opt);
103 MyPrivateData extension = MyPrivateData("EXTENSION");
104 MyPrivateData key_string[] = {
105 "Key #0", "Key #1", "Key #2", "Key #3",
106 "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
109 did = should = PR_FALSE;
110 for (keys = 0; keys < 4; ++keys)
112 rv = RCThread::NewPrivateIndex(&key[keys]);
113 key[keys + 4] = key[keys] + 4;
114 MY_ASSERT(PR_SUCCESS == rv);
116 PrintProgress(__LINE__);
118 /* the first four should be bu null, the last four undefined and null */
119 did = should = PR_FALSE;
120 for (keys = 0; keys < 8; ++keys)
122 pd = RCThread::GetPrivateData(key[keys]);
123 MY_ASSERT(NULL == pd);
125 PrintProgress(__LINE__);
127 /* initially set private data for new keys */
128 did = should = PR_FALSE;
129 for (keys = 0; keys < 4; ++keys)
131 rv = RCThread::SetPrivateData(key[keys], &key_string[keys]);
132 MY_ASSERT(PR_SUCCESS == rv);
134 PrintProgress(__LINE__);
136 /* re-assign the private data, albeit the same content */
137 did = PR_FALSE; should = PR_TRUE;
138 for (keys = 0; keys < 4; ++keys)
140 pd = RCThread::GetPrivateData(key[keys]);
141 PR_ASSERT(NULL != pd);
142 rv = RCThread::SetPrivateData(key[keys], &key_string[keys]);
143 MY_ASSERT(PR_SUCCESS == rv);
145 PrintProgress(__LINE__);
147 /* set private to <empty> */
148 did = PR_FALSE; should = PR_TRUE;
149 for (keys = 0; keys < 4; ++keys)
151 rv = RCThread::SetPrivateData(key[keys]);
152 MY_ASSERT(PR_SUCCESS == rv);
154 PrintProgress(__LINE__);
156 /* should all be null now */
157 did = should = PR_FALSE;
158 for (keys = 0; keys < 4; ++keys)
160 pd = RCThread::GetPrivateData(key[keys]);
161 PR_ASSERT(NULL == pd);
163 PrintProgress(__LINE__);
165 /* allocate another batch of keys and assign data to them */
166 did = should = PR_FALSE;
167 for (keys = 8; keys < 127; ++keys)
169 rv = RCThread::NewPrivateIndex(&key[keys]);
170 MY_ASSERT(PR_SUCCESS == rv);
171 rv = RCThread::SetPrivateData(key[keys], &extension);
172 MY_ASSERT(PR_SUCCESS == rv);
174 PrintProgress(__LINE__);
176 /* set all the extended slots to <empty> */
177 did = PR_FALSE; should = PR_TRUE;
178 for (keys = 8; keys < 127; ++keys)
180 rv = RCThread::SetPrivateData(key[keys]);
181 MY_ASSERT(PR_SUCCESS == rv);
183 PrintProgress(__LINE__);
185 /* set all the extended slots to <empty> again (noop) */
186 did = should = PR_FALSE;
187 for (keys = 8; keys < 127; ++keys)
189 rv = RCThread::SetPrivateData(key[keys]);
190 MY_ASSERT(PR_SUCCESS == rv);
193 if (debug) PR_fprintf(fout, "Creating thread\n");
194 thread = new MyThread();
195 if (debug) PR_fprintf(fout, "Starting thread\n");
197 if (debug) PR_fprintf(fout, "Joining thread\n");
198 (void)thread->Join();
199 if (debug) PR_fprintf(fout, "Joined thread\n");
201 failed |= (PR_FAILURE == RCPrimordialThread::Cleanup());
204 fout, "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED"));
206 return (failed) ? 1 : 0;
211 ** class MyPrivateData
213 MyPrivateData::~MyPrivateData()
216 fout, "MyPrivateData::~MyPrivateData[%s]\n",
217 (NULL != string) ? string : "NULL");
218 } /* MyPrivateData::~MyPrivateData */
220 MyPrivateData::MyPrivateData(): RCThreadPrivateData()
222 PR_fprintf(fout, "MyPrivateData::MyPrivateData()\n");
224 } /* MyPrivateData::MyPrivateData */
226 MyPrivateData::MyPrivateData(char* data): RCThreadPrivateData()
228 PR_fprintf(fout, "MyPrivateData::MyPrivateData(char* data)\n");
230 } /* MyPrivateData:: MyPrivateData */
232 MyPrivateData::MyPrivateData(const MyPrivateData& him): RCThreadPrivateData(him)
234 PR_fprintf(fout, "MyPrivateData::MyPrivateData(const MyPrivateData& him)\n");
236 } /* MyPrivateData:: MyPrivateData */
238 void MyPrivateData::Release()
240 if (should) did = PR_TRUE;
241 else failed = PR_TRUE;
242 } /* MyPrivateData::operator= */
247 MyThread::~MyThread() { }
248 MyThread::MyThread(): RCThread(RCThread::global, RCThread::joinable) { }
251 void MyThread::RootFunction()
255 const RCThreadPrivateData *pd;
257 MyPrivateData extension = MyPrivateData("EXTENSION");
258 MyPrivateData key_string[] = {
259 "Key #0", "Key #1", "Key #2", "Key #3",
260 "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"};
262 did = should = PR_FALSE;
263 for (keys = 0; keys < 8; ++keys)
265 pd = GetPrivateData(key[keys]);
266 MY_ASSERT(NULL == pd);
268 PrintProgress(__LINE__);
270 did = should = PR_FALSE;
271 for (keys = 0; keys < 4; ++keys)
273 rv = SetPrivateData(keys, &key_string[keys]);
274 MY_ASSERT(PR_SUCCESS == rv);
276 PrintProgress(__LINE__);
279 did = should = PR_FALSE;
280 for (keys = 4; keys < 8; ++keys)
282 rv = SetPrivateData(keys, &key_string[keys]);
283 MY_ASSERT(PR_FAILURE == rv);
285 PrintProgress(__LINE__);
288 did = PR_FALSE; should = PR_TRUE;
289 for (keys = 0; keys < 4; ++keys)
291 rv = SetPrivateData(key[keys], &key_string[keys]);
292 MY_ASSERT(PR_SUCCESS == rv);
294 PrintProgress(__LINE__);
296 did = PR_FALSE; should = PR_TRUE;
297 for (keys = 0; keys < 4; ++keys)
299 rv = SetPrivateData(key[keys]);
300 MY_ASSERT(PR_SUCCESS == rv);
302 PrintProgress(__LINE__);
304 did = should = PR_FALSE;
305 for (keys = 0; keys < 4; ++keys)
307 rv = SetPrivateData(key[keys]);
308 MY_ASSERT(PR_SUCCESS == rv);
310 PrintProgress(__LINE__);
312 did = should = PR_FALSE;
313 for (keys = 8; keys < 127; ++keys)
315 rv = SetPrivateData(key[keys], &extension);
316 MY_ASSERT(PR_SUCCESS == rv);
318 PrintProgress(__LINE__);
320 did = PR_FALSE; should = PR_TRUE;
321 for (keys = 8; keys < 127; ++keys)
323 rv = SetPrivateData(key[keys]);
324 MY_ASSERT(PR_SUCCESS == rv);
326 PrintProgress(__LINE__);
328 did = should = PR_FALSE;
329 for (keys = 8; keys < 127; ++keys)
331 rv = SetPrivateData(key[keys]);
332 MY_ASSERT(PR_SUCCESS == rv);
334 } /* MyThread::RootFunction */