tpd.cpp (8749B)
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/. */ 5 6 /* 7 ** File: tpd.cpp 8 ** Description: Exercising the thread private data bailywick. 9 */ 10 11 #include "prlog.h" 12 #include "prprf.h" 13 #include "rcthread.h" 14 15 #include <string.h> 16 17 #include "plgetopt.h" 18 19 /* 20 ** class MyThread 21 */ 22 class MyThread: public RCThread 23 { 24 public: 25 MyThread(); 26 27 private: 28 ~MyThread(); 29 void RootFunction(); 30 }; /* MyThread */ 31 32 /* 33 ** class MyPrivateData 34 */ 35 class MyPrivateData: public RCThreadPrivateData 36 { 37 public: 38 virtual ~MyPrivateData(); 39 40 MyPrivateData(); 41 MyPrivateData(char*); 42 MyPrivateData(const MyPrivateData&); 43 44 void Release(); 45 46 private: 47 char *string; 48 }; /* MyPrivateData */ 49 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; 56 57 static void PrintProgress(PRIntn line) 58 { 59 failed = failed || (should && !did); 60 failed = failed || (!should && did); 61 if (debug > 0) 62 { 63 PR_fprintf( 64 fout, "@ line %d destructor should %shave been called and was%s\n", 65 line, ((should) ? "" : "NOT "), ((did) ? "" : " NOT")); 66 } 67 } /* PrintProgress */ 68 69 static void MyAssert(const char *expr, const char *file, PRIntn line) 70 { 71 if (debug > 0) { 72 (void)PR_fprintf(fout, "'%s' in file: %s: %d\n", expr, file, line); 73 } 74 } /* MyAssert */ 75 76 #define MY_ASSERT(_expr) \ 77 ((_expr)?((void)0):MyAssert(# _expr,__FILE__,__LINE__)) 78 79 int main(PRIntn argc, char *argv[]) 80 { 81 PRStatus rv; 82 PRUintn keys; 83 MyThread *thread; 84 const RCThreadPrivateData *pd; 85 PLOptStatus os; 86 PLOptState *opt = PL_CreateOptState(argc, argv, "d"); 87 RCThread *primordial = RCThread::WrapPrimordialThread(); 88 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 89 { 90 if (PL_OPT_BAD == os) { 91 continue; 92 } 93 switch (opt->option) 94 { 95 case 'd': /* debug mode */ 96 debug = PR_TRUE; 97 break; 98 default: 99 break; 100 } 101 } 102 PL_DestroyOptState(opt); 103 104 fout = PR_STDOUT; 105 106 MyPrivateData extension = MyPrivateData("EXTENSION"); 107 MyPrivateData key_string[] = { 108 "Key #0", "Key #1", "Key #2", "Key #3", 109 "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8" 110 }; 111 112 113 did = should = PR_FALSE; 114 for (keys = 0; keys < 4; ++keys) 115 { 116 rv = RCThread::NewPrivateIndex(&key[keys]); 117 key[keys + 4] = key[keys] + 4; 118 MY_ASSERT(PR_SUCCESS == rv); 119 } 120 PrintProgress(__LINE__); 121 122 /* the first four should be bu null, the last four undefined and null */ 123 did = should = PR_FALSE; 124 for (keys = 0; keys < 8; ++keys) 125 { 126 pd = RCThread::GetPrivateData(key[keys]); 127 MY_ASSERT(NULL == pd); 128 } 129 PrintProgress(__LINE__); 130 131 /* initially set private data for new keys */ 132 did = should = PR_FALSE; 133 for (keys = 0; keys < 4; ++keys) 134 { 135 rv = RCThread::SetPrivateData(key[keys], &key_string[keys]); 136 MY_ASSERT(PR_SUCCESS == rv); 137 } 138 PrintProgress(__LINE__); 139 140 /* re-assign the private data, albeit the same content */ 141 did = PR_FALSE; should = PR_TRUE; 142 for (keys = 0; keys < 4; ++keys) 143 { 144 pd = RCThread::GetPrivateData(key[keys]); 145 PR_ASSERT(NULL != pd); 146 rv = RCThread::SetPrivateData(key[keys], &key_string[keys]); 147 MY_ASSERT(PR_SUCCESS == rv); 148 } 149 PrintProgress(__LINE__); 150 151 /* set private to <empty> */ 152 did = PR_FALSE; should = PR_TRUE; 153 for (keys = 0; keys < 4; ++keys) 154 { 155 rv = RCThread::SetPrivateData(key[keys]); 156 MY_ASSERT(PR_SUCCESS == rv); 157 } 158 PrintProgress(__LINE__); 159 160 /* should all be null now */ 161 did = should = PR_FALSE; 162 for (keys = 0; keys < 4; ++keys) 163 { 164 pd = RCThread::GetPrivateData(key[keys]); 165 PR_ASSERT(NULL == pd); 166 } 167 PrintProgress(__LINE__); 168 169 /* allocate another batch of keys and assign data to them */ 170 did = should = PR_FALSE; 171 for (keys = 8; keys < 127; ++keys) 172 { 173 rv = RCThread::NewPrivateIndex(&key[keys]); 174 MY_ASSERT(PR_SUCCESS == rv); 175 rv = RCThread::SetPrivateData(key[keys], &extension); 176 MY_ASSERT(PR_SUCCESS == rv); 177 } 178 PrintProgress(__LINE__); 179 180 /* set all the extended slots to <empty> */ 181 did = PR_FALSE; should = PR_TRUE; 182 for (keys = 8; keys < 127; ++keys) 183 { 184 rv = RCThread::SetPrivateData(key[keys]); 185 MY_ASSERT(PR_SUCCESS == rv); 186 } 187 PrintProgress(__LINE__); 188 189 /* set all the extended slots to <empty> again (noop) */ 190 did = should = PR_FALSE; 191 for (keys = 8; keys < 127; ++keys) 192 { 193 rv = RCThread::SetPrivateData(key[keys]); 194 MY_ASSERT(PR_SUCCESS == rv); 195 } 196 197 if (debug) { 198 PR_fprintf(fout, "Creating thread\n"); 199 } 200 thread = new MyThread(); 201 if (debug) { 202 PR_fprintf(fout, "Starting thread\n"); 203 } 204 thread->Start(); 205 if (debug) { 206 PR_fprintf(fout, "Joining thread\n"); 207 } 208 (void)thread->Join(); 209 if (debug) { 210 PR_fprintf(fout, "Joined thread\n"); 211 } 212 213 failed |= (PR_FAILURE == RCPrimordialThread::Cleanup()); 214 215 (void)PR_fprintf( 216 fout, "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED")); 217 218 return (failed) ? 1 : 0; 219 220 } /* main */ 221 222 /* 223 ** class MyPrivateData 224 */ 225 MyPrivateData::~MyPrivateData() 226 { 227 PR_fprintf( 228 fout, "MyPrivateData::~MyPrivateData[%s]\n", 229 (NULL != string) ? string : "NULL"); 230 } /* MyPrivateData::~MyPrivateData */ 231 232 MyPrivateData::MyPrivateData(): RCThreadPrivateData() 233 { 234 PR_fprintf(fout, "MyPrivateData::MyPrivateData()\n"); 235 string = NULL; 236 } /* MyPrivateData::MyPrivateData */ 237 238 MyPrivateData::MyPrivateData(char* data): RCThreadPrivateData() 239 { 240 PR_fprintf(fout, "MyPrivateData::MyPrivateData(char* data)\n"); 241 string = data; 242 } /* MyPrivateData:: MyPrivateData */ 243 244 MyPrivateData::MyPrivateData(const MyPrivateData& him): RCThreadPrivateData(him) 245 { 246 PR_fprintf(fout, "MyPrivateData::MyPrivateData(const MyPrivateData& him)\n"); 247 string = him.string; 248 } /* MyPrivateData:: MyPrivateData */ 249 250 void MyPrivateData::Release() 251 { 252 if (should) { 253 did = PR_TRUE; 254 } 255 else { 256 failed = PR_TRUE; 257 } 258 } /* MyPrivateData::operator= */ 259 260 /* 261 ** class MyThread 262 */ 263 MyThread::~MyThread() { } 264 MyThread::MyThread(): RCThread(RCThread::global, RCThread::joinable) { } 265 266 267 void MyThread::RootFunction() 268 { 269 PRStatus rv; 270 PRUintn keys; 271 const RCThreadPrivateData *pd; 272 273 MyPrivateData extension = MyPrivateData("EXTENSION"); 274 MyPrivateData key_string[] = { 275 "Key #0", "Key #1", "Key #2", "Key #3", 276 "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8" 277 }; 278 279 did = should = PR_FALSE; 280 for (keys = 0; keys < 8; ++keys) 281 { 282 pd = GetPrivateData(key[keys]); 283 MY_ASSERT(NULL == pd); 284 } 285 PrintProgress(__LINE__); 286 287 did = should = PR_FALSE; 288 for (keys = 0; keys < 4; ++keys) 289 { 290 rv = SetPrivateData(keys, &key_string[keys]); 291 MY_ASSERT(PR_SUCCESS == rv); 292 } 293 PrintProgress(__LINE__); 294 295 #if !defined(DEBUG) 296 did = should = PR_FALSE; 297 for (keys = 4; keys < 8; ++keys) 298 { 299 rv = SetPrivateData(keys, &key_string[keys]); 300 MY_ASSERT(PR_FAILURE == rv); 301 } 302 PrintProgress(__LINE__); 303 #endif 304 305 did = PR_FALSE; should = PR_TRUE; 306 for (keys = 0; keys < 4; ++keys) 307 { 308 rv = SetPrivateData(key[keys], &key_string[keys]); 309 MY_ASSERT(PR_SUCCESS == rv); 310 } 311 PrintProgress(__LINE__); 312 313 did = PR_FALSE; should = PR_TRUE; 314 for (keys = 0; keys < 4; ++keys) 315 { 316 rv = SetPrivateData(key[keys]); 317 MY_ASSERT(PR_SUCCESS == rv); 318 } 319 PrintProgress(__LINE__); 320 321 did = should = PR_FALSE; 322 for (keys = 0; keys < 4; ++keys) 323 { 324 rv = SetPrivateData(key[keys]); 325 MY_ASSERT(PR_SUCCESS == rv); 326 } 327 PrintProgress(__LINE__); 328 329 did = should = PR_FALSE; 330 for (keys = 8; keys < 127; ++keys) 331 { 332 rv = SetPrivateData(key[keys], &extension); 333 MY_ASSERT(PR_SUCCESS == rv); 334 } 335 PrintProgress(__LINE__); 336 337 did = PR_FALSE; should = PR_TRUE; 338 for (keys = 8; keys < 127; ++keys) 339 { 340 rv = SetPrivateData(key[keys]); 341 MY_ASSERT(PR_SUCCESS == rv); 342 } 343 PrintProgress(__LINE__); 344 345 did = should = PR_FALSE; 346 for (keys = 8; keys < 127; ++keys) 347 { 348 rv = SetPrivateData(key[keys]); 349 MY_ASSERT(PR_SUCCESS == rv); 350 } 351 } /* MyThread::RootFunction */ 352 353 /* tpd.c */