1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/cplus/tests/tpd.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,336 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 +** File: tpd.cpp 1.11 +** Description: Exercising the thread private data bailywick. 1.12 +*/ 1.13 + 1.14 +#include "prlog.h" 1.15 +#include "prprf.h" 1.16 +#include "rcthread.h" 1.17 + 1.18 +#include <string.h> 1.19 + 1.20 +#include "plgetopt.h" 1.21 + 1.22 +/* 1.23 +** class MyThread 1.24 +*/ 1.25 +class MyThread: public RCThread 1.26 +{ 1.27 +public: 1.28 + MyThread(); 1.29 + 1.30 +private: 1.31 + ~MyThread(); 1.32 + void RootFunction(); 1.33 +}; /* MyThread */ 1.34 + 1.35 +/* 1.36 +** class MyPrivateData 1.37 +*/ 1.38 +class MyPrivateData: public RCThreadPrivateData 1.39 +{ 1.40 +public: 1.41 + virtual ~MyPrivateData(); 1.42 + 1.43 + MyPrivateData(); 1.44 + MyPrivateData(char*); 1.45 + MyPrivateData(const MyPrivateData&); 1.46 + 1.47 + void Release(); 1.48 + 1.49 +private: 1.50 + char *string; 1.51 +}; /* MyPrivateData */ 1.52 + 1.53 +static PRUintn key[128]; 1.54 +static PRIntn debug = 0; 1.55 +static PRBool failed = PR_FALSE; 1.56 +static PRBool should = PR_TRUE; 1.57 +static PRBool did = PR_TRUE; 1.58 +static PRFileDesc *fout = NULL; 1.59 + 1.60 +static void PrintProgress(PRIntn line) 1.61 +{ 1.62 + failed = failed || (should && !did); 1.63 + failed = failed || (!should && did); 1.64 + if (debug > 0) 1.65 + { 1.66 + PR_fprintf( 1.67 + fout, "@ line %d destructor should %shave been called and was%s\n", 1.68 + line, ((should) ? "" : "NOT "), ((did) ? "" : " NOT")); 1.69 + } 1.70 +} /* PrintProgress */ 1.71 + 1.72 +static void MyAssert(const char *expr, const char *file, PRIntn line) 1.73 +{ 1.74 + if (debug > 0) 1.75 + (void)PR_fprintf(fout, "'%s' in file: %s: %d\n", expr, file, line); 1.76 +} /* MyAssert */ 1.77 + 1.78 +#define MY_ASSERT(_expr) \ 1.79 + ((_expr)?((void)0):MyAssert(# _expr,__FILE__,__LINE__)) 1.80 + 1.81 +int main(PRIntn argc, char *argv[]) 1.82 +{ 1.83 + PRStatus rv; 1.84 + PRUintn keys; 1.85 + MyThread *thread; 1.86 + const RCThreadPrivateData *pd; 1.87 + PLOptStatus os; 1.88 + PLOptState *opt = PL_CreateOptState(argc, argv, "d"); 1.89 + RCThread *primordial = RCThread::WrapPrimordialThread(); 1.90 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.91 + { 1.92 + if (PL_OPT_BAD == os) continue; 1.93 + switch (opt->option) 1.94 + { 1.95 + case 'd': /* debug mode */ 1.96 + debug = PR_TRUE; 1.97 + break; 1.98 + default: 1.99 + break; 1.100 + } 1.101 + } 1.102 + PL_DestroyOptState(opt); 1.103 + 1.104 + fout = PR_STDOUT; 1.105 + 1.106 + MyPrivateData extension = MyPrivateData("EXTENSION"); 1.107 + MyPrivateData key_string[] = { 1.108 + "Key #0", "Key #1", "Key #2", "Key #3", 1.109 + "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"}; 1.110 + 1.111 + 1.112 + did = should = PR_FALSE; 1.113 + for (keys = 0; keys < 4; ++keys) 1.114 + { 1.115 + rv = RCThread::NewPrivateIndex(&key[keys]); 1.116 + key[keys + 4] = key[keys] + 4; 1.117 + MY_ASSERT(PR_SUCCESS == rv); 1.118 + } 1.119 + PrintProgress(__LINE__); 1.120 + 1.121 + /* the first four should be bu null, the last four undefined and null */ 1.122 + did = should = PR_FALSE; 1.123 + for (keys = 0; keys < 8; ++keys) 1.124 + { 1.125 + pd = RCThread::GetPrivateData(key[keys]); 1.126 + MY_ASSERT(NULL == pd); 1.127 + } 1.128 + PrintProgress(__LINE__); 1.129 + 1.130 + /* initially set private data for new keys */ 1.131 + did = should = PR_FALSE; 1.132 + for (keys = 0; keys < 4; ++keys) 1.133 + { 1.134 + rv = RCThread::SetPrivateData(key[keys], &key_string[keys]); 1.135 + MY_ASSERT(PR_SUCCESS == rv); 1.136 + } 1.137 + PrintProgress(__LINE__); 1.138 + 1.139 + /* re-assign the private data, albeit the same content */ 1.140 + did = PR_FALSE; should = PR_TRUE; 1.141 + for (keys = 0; keys < 4; ++keys) 1.142 + { 1.143 + pd = RCThread::GetPrivateData(key[keys]); 1.144 + PR_ASSERT(NULL != pd); 1.145 + rv = RCThread::SetPrivateData(key[keys], &key_string[keys]); 1.146 + MY_ASSERT(PR_SUCCESS == rv); 1.147 + } 1.148 + PrintProgress(__LINE__); 1.149 + 1.150 + /* set private to <empty> */ 1.151 + did = PR_FALSE; should = PR_TRUE; 1.152 + for (keys = 0; keys < 4; ++keys) 1.153 + { 1.154 + rv = RCThread::SetPrivateData(key[keys]); 1.155 + MY_ASSERT(PR_SUCCESS == rv); 1.156 + } 1.157 + PrintProgress(__LINE__); 1.158 + 1.159 + /* should all be null now */ 1.160 + did = should = PR_FALSE; 1.161 + for (keys = 0; keys < 4; ++keys) 1.162 + { 1.163 + pd = RCThread::GetPrivateData(key[keys]); 1.164 + PR_ASSERT(NULL == pd); 1.165 + } 1.166 + PrintProgress(__LINE__); 1.167 + 1.168 + /* allocate another batch of keys and assign data to them */ 1.169 + did = should = PR_FALSE; 1.170 + for (keys = 8; keys < 127; ++keys) 1.171 + { 1.172 + rv = RCThread::NewPrivateIndex(&key[keys]); 1.173 + MY_ASSERT(PR_SUCCESS == rv); 1.174 + rv = RCThread::SetPrivateData(key[keys], &extension); 1.175 + MY_ASSERT(PR_SUCCESS == rv); 1.176 + } 1.177 + PrintProgress(__LINE__); 1.178 + 1.179 + /* set all the extended slots to <empty> */ 1.180 + did = PR_FALSE; should = PR_TRUE; 1.181 + for (keys = 8; keys < 127; ++keys) 1.182 + { 1.183 + rv = RCThread::SetPrivateData(key[keys]); 1.184 + MY_ASSERT(PR_SUCCESS == rv); 1.185 + } 1.186 + PrintProgress(__LINE__); 1.187 + 1.188 + /* set all the extended slots to <empty> again (noop) */ 1.189 + did = should = PR_FALSE; 1.190 + for (keys = 8; keys < 127; ++keys) 1.191 + { 1.192 + rv = RCThread::SetPrivateData(key[keys]); 1.193 + MY_ASSERT(PR_SUCCESS == rv); 1.194 + } 1.195 + 1.196 + if (debug) PR_fprintf(fout, "Creating thread\n"); 1.197 + thread = new MyThread(); 1.198 + if (debug) PR_fprintf(fout, "Starting thread\n"); 1.199 + thread->Start(); 1.200 + if (debug) PR_fprintf(fout, "Joining thread\n"); 1.201 + (void)thread->Join(); 1.202 + if (debug) PR_fprintf(fout, "Joined thread\n"); 1.203 + 1.204 + failed |= (PR_FAILURE == RCPrimordialThread::Cleanup()); 1.205 + 1.206 + (void)PR_fprintf( 1.207 + fout, "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED")); 1.208 + 1.209 + return (failed) ? 1 : 0; 1.210 + 1.211 +} /* main */ 1.212 + 1.213 +/* 1.214 +** class MyPrivateData 1.215 +*/ 1.216 +MyPrivateData::~MyPrivateData() 1.217 +{ 1.218 + PR_fprintf( 1.219 + fout, "MyPrivateData::~MyPrivateData[%s]\n", 1.220 + (NULL != string) ? string : "NULL"); 1.221 +} /* MyPrivateData::~MyPrivateData */ 1.222 + 1.223 +MyPrivateData::MyPrivateData(): RCThreadPrivateData() 1.224 +{ 1.225 + PR_fprintf(fout, "MyPrivateData::MyPrivateData()\n"); 1.226 + string = NULL; 1.227 +} /* MyPrivateData::MyPrivateData */ 1.228 + 1.229 +MyPrivateData::MyPrivateData(char* data): RCThreadPrivateData() 1.230 +{ 1.231 + PR_fprintf(fout, "MyPrivateData::MyPrivateData(char* data)\n"); 1.232 + string = data; 1.233 +} /* MyPrivateData:: MyPrivateData */ 1.234 + 1.235 +MyPrivateData::MyPrivateData(const MyPrivateData& him): RCThreadPrivateData(him) 1.236 +{ 1.237 + PR_fprintf(fout, "MyPrivateData::MyPrivateData(const MyPrivateData& him)\n"); 1.238 + string = him.string; 1.239 +} /* MyPrivateData:: MyPrivateData */ 1.240 + 1.241 +void MyPrivateData::Release() 1.242 +{ 1.243 + if (should) did = PR_TRUE; 1.244 + else failed = PR_TRUE; 1.245 +} /* MyPrivateData::operator= */ 1.246 + 1.247 +/* 1.248 +** class MyThread 1.249 +*/ 1.250 +MyThread::~MyThread() { } 1.251 +MyThread::MyThread(): RCThread(RCThread::global, RCThread::joinable) { } 1.252 + 1.253 + 1.254 +void MyThread::RootFunction() 1.255 +{ 1.256 + PRStatus rv; 1.257 + PRUintn keys; 1.258 + const RCThreadPrivateData *pd; 1.259 + 1.260 + MyPrivateData extension = MyPrivateData("EXTENSION"); 1.261 + MyPrivateData key_string[] = { 1.262 + "Key #0", "Key #1", "Key #2", "Key #3", 1.263 + "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"}; 1.264 + 1.265 + did = should = PR_FALSE; 1.266 + for (keys = 0; keys < 8; ++keys) 1.267 + { 1.268 + pd = GetPrivateData(key[keys]); 1.269 + MY_ASSERT(NULL == pd); 1.270 + } 1.271 + PrintProgress(__LINE__); 1.272 + 1.273 + did = should = PR_FALSE; 1.274 + for (keys = 0; keys < 4; ++keys) 1.275 + { 1.276 + rv = SetPrivateData(keys, &key_string[keys]); 1.277 + MY_ASSERT(PR_SUCCESS == rv); 1.278 + } 1.279 + PrintProgress(__LINE__); 1.280 + 1.281 +#if !defined(DEBUG) 1.282 + did = should = PR_FALSE; 1.283 + for (keys = 4; keys < 8; ++keys) 1.284 + { 1.285 + rv = SetPrivateData(keys, &key_string[keys]); 1.286 + MY_ASSERT(PR_FAILURE == rv); 1.287 + } 1.288 + PrintProgress(__LINE__); 1.289 +#endif 1.290 + 1.291 + did = PR_FALSE; should = PR_TRUE; 1.292 + for (keys = 0; keys < 4; ++keys) 1.293 + { 1.294 + rv = SetPrivateData(key[keys], &key_string[keys]); 1.295 + MY_ASSERT(PR_SUCCESS == rv); 1.296 + } 1.297 + PrintProgress(__LINE__); 1.298 + 1.299 + did = PR_FALSE; should = PR_TRUE; 1.300 + for (keys = 0; keys < 4; ++keys) 1.301 + { 1.302 + rv = SetPrivateData(key[keys]); 1.303 + MY_ASSERT(PR_SUCCESS == rv); 1.304 + } 1.305 + PrintProgress(__LINE__); 1.306 + 1.307 + did = should = PR_FALSE; 1.308 + for (keys = 0; keys < 4; ++keys) 1.309 + { 1.310 + rv = SetPrivateData(key[keys]); 1.311 + MY_ASSERT(PR_SUCCESS == rv); 1.312 + } 1.313 + PrintProgress(__LINE__); 1.314 + 1.315 + did = should = PR_FALSE; 1.316 + for (keys = 8; keys < 127; ++keys) 1.317 + { 1.318 + rv = SetPrivateData(key[keys], &extension); 1.319 + MY_ASSERT(PR_SUCCESS == rv); 1.320 + } 1.321 + PrintProgress(__LINE__); 1.322 + 1.323 + did = PR_FALSE; should = PR_TRUE; 1.324 + for (keys = 8; keys < 127; ++keys) 1.325 + { 1.326 + rv = SetPrivateData(key[keys]); 1.327 + MY_ASSERT(PR_SUCCESS == rv); 1.328 + } 1.329 + PrintProgress(__LINE__); 1.330 + 1.331 + did = should = PR_FALSE; 1.332 + for (keys = 8; keys < 127; ++keys) 1.333 + { 1.334 + rv = SetPrivateData(key[keys]); 1.335 + MY_ASSERT(PR_SUCCESS == rv); 1.336 + } 1.337 +} /* MyThread::RootFunction */ 1.338 + 1.339 +/* tpd.c */