| [1016] | 1 | // ********************************************************************** | 
|---|
|  | 2 | // | 
|---|
|  | 3 | // Copyright (c) 2000 | 
|---|
|  | 4 | // Object Oriented Concepts, Inc. | 
|---|
|  | 5 | // Billerica, MA, USA | 
|---|
|  | 6 | // | 
|---|
|  | 7 | // All Rights Reserved | 
|---|
|  | 8 | // | 
|---|
|  | 9 | // ********************************************************************** | 
|---|
|  | 10 |  | 
|---|
|  | 11 | #include <JTC/Types.h> | 
|---|
|  | 12 | #include <JTC/Syscall.h> | 
|---|
|  | 13 | #include <JTC/Mutex.h> | 
|---|
|  | 14 | #include <JTC/Handle.h> | 
|---|
|  | 15 | #include <JTC/HandleI.h> | 
|---|
|  | 16 | #include <JTC/Event.h> | 
|---|
|  | 17 | #include <JTC/Cond.h> | 
|---|
|  | 18 | #include <JTC/Monitor.h> | 
|---|
|  | 19 | #include <JTC/Exception.h> | 
|---|
|  | 20 | #include <JTC/Thread.h> | 
|---|
|  | 21 | #include <JTC/ThreadGroup.h> | 
|---|
|  | 22 | #include <JTC/Runnable.h> | 
|---|
|  | 23 | #include <JTC/Sync.h> | 
|---|
|  | 24 |  | 
|---|
|  | 25 | #include <string.h> | 
|---|
|  | 26 |  | 
|---|
|  | 27 | #ifndef HAVE_NO_EXPLICIT_TEMPLATES | 
|---|
|  | 28 | template class JTCHandleT<JTCThreadGroup>; | 
|---|
|  | 29 | #else | 
|---|
|  | 30 | #  ifdef HAVE_PRAGMA_DEFINE | 
|---|
|  | 31 | #    pragma define(JTCHandleT<JTCThreadGroup>) | 
|---|
|  | 32 | #  endif | 
|---|
|  | 33 | #endif | 
|---|
|  | 34 |  | 
|---|
|  | 35 | #ifdef HAVE_STD_IOSTREAM | 
|---|
|  | 36 | using namespace std; | 
|---|
|  | 37 | #endif | 
|---|
|  | 38 |  | 
|---|
|  | 39 | // ---------------------------------------------------------------------- | 
|---|
|  | 40 | // JTCThreadGroup::JTCThreadGroupSet public member implementation | 
|---|
|  | 41 | // ---------------------------------------------------------------------- | 
|---|
|  | 42 |  | 
|---|
|  | 43 | // | 
|---|
|  | 44 | // Allocate n members. | 
|---|
|  | 45 | // | 
|---|
|  | 46 | inline void | 
|---|
|  | 47 | JTCThreadGroup::JTCThreadGroupSet::allocate(int n) | 
|---|
|  | 48 | { | 
|---|
|  | 49 | len_ = n; | 
|---|
|  | 50 | handles_ = new JTCThreadGroupHandle[n]; | 
|---|
|  | 51 | } | 
|---|
|  | 52 |  | 
|---|
|  | 53 | // | 
|---|
|  | 54 | // Return the number of elements in the set. | 
|---|
|  | 55 | // | 
|---|
|  | 56 | inline int | 
|---|
|  | 57 | JTCThreadGroup::JTCThreadGroupSet::length() const | 
|---|
|  | 58 | { | 
|---|
|  | 59 | return len_; | 
|---|
|  | 60 | } | 
|---|
|  | 61 |  | 
|---|
|  | 62 | // | 
|---|
|  | 63 | // Return a reference to the i'th element. | 
|---|
|  | 64 | // | 
|---|
|  | 65 | inline JTCThreadGroupHandle& | 
|---|
|  | 66 | JTCThreadGroup::JTCThreadGroupSet::operator[](int i) | 
|---|
|  | 67 | { | 
|---|
|  | 68 | return handles_[i]; | 
|---|
|  | 69 | } | 
|---|
|  | 70 |  | 
|---|
|  | 71 | // ---------------------------------------------------------------------- | 
|---|
|  | 72 | // JTCThreadGroup private member implementation | 
|---|
|  | 73 | // ---------------------------------------------------------------------- | 
|---|
|  | 74 |  | 
|---|
|  | 75 | // | 
|---|
|  | 76 | // Create a snapshot of current child ThreadGroups. | 
|---|
|  | 77 | // | 
|---|
|  | 78 | void | 
|---|
|  | 79 | JTCThreadGroup::createGroupSnapshot(JTCThreadGroupSet& set) const | 
|---|
|  | 80 | { | 
|---|
|  | 81 | set.allocate(ngroups_); | 
|---|
|  | 82 | for(int i = 0; i < ngroups_; ++i) | 
|---|
|  | 83 | { | 
|---|
|  | 84 | set[i] = groups_[i]; | 
|---|
|  | 85 | } | 
|---|
|  | 86 | } | 
|---|
|  | 87 |  | 
|---|
|  | 88 | // | 
|---|
|  | 89 | // Add a ThreadGroup to my child list. | 
|---|
|  | 90 | // | 
|---|
|  | 91 | void | 
|---|
|  | 92 | JTCThreadGroup::add(JTCThreadGroup* g) | 
|---|
|  | 93 | { | 
|---|
|  | 94 | JTCSynchronized sync(*this); | 
|---|
|  | 95 | if(destroyed_) | 
|---|
|  | 96 | { | 
|---|
|  | 97 | throw JTCIllegalThreadStateException(); | 
|---|
|  | 98 | } | 
|---|
|  | 99 | // | 
|---|
|  | 100 | // No children yet? | 
|---|
|  | 101 | // | 
|---|
|  | 102 | if(groups_ == 0) | 
|---|
|  | 103 | { | 
|---|
|  | 104 | groups_ = new JTCThreadGroup*[4]; | 
|---|
|  | 105 | groupsLength_ = 4; | 
|---|
|  | 106 | } | 
|---|
|  | 107 | // | 
|---|
|  | 108 | // Time to grow array? | 
|---|
|  | 109 | // | 
|---|
|  | 110 | else if(ngroups_ == groupsLength_) | 
|---|
|  | 111 | { | 
|---|
|  | 112 | // | 
|---|
|  | 113 | // Allocate memory and then copy...  This is more exception | 
|---|
|  | 114 | // safe. | 
|---|
|  | 115 | // | 
|---|
|  | 116 | int newGroupsLength = ngroups_*2; | 
|---|
|  | 117 | JTCThreadGroup** newGroups = new JTCThreadGroup*[newGroupsLength]; | 
|---|
|  | 118 | for(int i = 0; i < ngroups_; ++i) | 
|---|
|  | 119 | { | 
|---|
|  | 120 | newGroups[i] = groups_[i]; | 
|---|
|  | 121 | } | 
|---|
|  | 122 |  | 
|---|
|  | 123 | delete[] groups_; | 
|---|
|  | 124 | groups_ = newGroups; | 
|---|
|  | 125 | groupsLength_ = newGroupsLength; | 
|---|
|  | 126 | } | 
|---|
|  | 127 |  | 
|---|
|  | 128 | // | 
|---|
|  | 129 | // Add the group to the child list. | 
|---|
|  | 130 | // | 
|---|
|  | 131 | groups_[ngroups_] = g; | 
|---|
|  | 132 | ++ngroups_; | 
|---|
|  | 133 | } | 
|---|
|  | 134 |  | 
|---|
|  | 135 | // | 
|---|
|  | 136 | // Remove a ThreadGroup from my child list. | 
|---|
|  | 137 | // | 
|---|
|  | 138 | void | 
|---|
|  | 139 | JTCThreadGroup::remove(JTCThreadGroup* g) | 
|---|
|  | 140 | { | 
|---|
|  | 141 | JTCSynchronized sync(*this); | 
|---|
|  | 142 | if(destroyed_) | 
|---|
|  | 143 | { | 
|---|
|  | 144 | throw JTCIllegalThreadStateException(); | 
|---|
|  | 145 | } | 
|---|
|  | 146 |  | 
|---|
|  | 147 | for(int i =0 ; i < ngroups_; ++i) | 
|---|
|  | 148 | { | 
|---|
|  | 149 | if(groups_[i] == g) | 
|---|
|  | 150 | { | 
|---|
|  | 151 | --ngroups_; | 
|---|
|  | 152 | for(int j = i; j < ngroups_; ++j) | 
|---|
|  | 153 | { | 
|---|
|  | 154 | groups_[j] = groups_[j+1]; | 
|---|
|  | 155 | } | 
|---|
|  | 156 | groups_[ngroups_] = 0; | 
|---|
|  | 157 | } | 
|---|
|  | 158 | } | 
|---|
|  | 159 |  | 
|---|
|  | 160 | // | 
|---|
|  | 161 | // If we remove the last thread then notify the ThreadGroups | 
|---|
|  | 162 | // monitor. | 
|---|
|  | 163 | // | 
|---|
|  | 164 | if(nthreads_ == 0) | 
|---|
|  | 165 | { | 
|---|
|  | 166 | notifyAll(); | 
|---|
|  | 167 | } | 
|---|
|  | 168 |  | 
|---|
|  | 169 | // | 
|---|
|  | 170 | // If we've gotten rid of all threads and ThreadGroups then | 
|---|
|  | 171 | // destroy the ThreadGroup. | 
|---|
|  | 172 | // | 
|---|
|  | 173 | if(daemon_ && nthreads_ == 0 && ngroups_ == 0) | 
|---|
|  | 174 | { | 
|---|
|  | 175 | destroy(); | 
|---|
|  | 176 | } | 
|---|
|  | 177 | } | 
|---|
|  | 178 |  | 
|---|
|  | 179 | // | 
|---|
|  | 180 | // This code is present to deal with internal compilation errors | 
|---|
|  | 181 | // in gcc 2.7.2 | 
|---|
|  | 182 | // | 
|---|
|  | 183 | void | 
|---|
|  | 184 | copy_it(JTCThreadHandle* from, int len, JTCThreadHandle* to) | 
|---|
|  | 185 | { | 
|---|
|  | 186 | for (int i =0; i < len; ++i) | 
|---|
|  | 187 | { | 
|---|
|  | 188 | to[i] = from[i]; | 
|---|
|  | 189 | } | 
|---|
|  | 190 | } | 
|---|
|  | 191 |  | 
|---|
|  | 192 | void | 
|---|
|  | 193 | delete_it(JTCThreadHandle* it) | 
|---|
|  | 194 | { | 
|---|
|  | 195 | delete[] it; | 
|---|
|  | 196 | } | 
|---|
|  | 197 |  | 
|---|
|  | 198 | // | 
|---|
|  | 199 | // End internal compilation error code | 
|---|
|  | 200 | // | 
|---|
|  | 201 |  | 
|---|
|  | 202 | // | 
|---|
|  | 203 | // Add a thread to my thread set. | 
|---|
|  | 204 | // | 
|---|
|  | 205 | void | 
|---|
|  | 206 | JTCThreadGroup::add(JTCThreadHandle t) | 
|---|
|  | 207 | { | 
|---|
|  | 208 | JTCSynchronized sync(*this); | 
|---|
|  | 209 |  | 
|---|
|  | 210 | if(destroyed_) | 
|---|
|  | 211 | { | 
|---|
|  | 212 | throw JTCIllegalThreadStateException(); | 
|---|
|  | 213 | } | 
|---|
|  | 214 |  | 
|---|
|  | 215 |  | 
|---|
|  | 216 | // | 
|---|
|  | 217 | // No threads yet? | 
|---|
|  | 218 | // | 
|---|
|  | 219 | if(threads_ == 0) | 
|---|
|  | 220 | { | 
|---|
|  | 221 | threads_ = new JTCThreadHandle[4]; | 
|---|
|  | 222 | threadsLength_ = 4; | 
|---|
|  | 223 | } | 
|---|
|  | 224 | // | 
|---|
|  | 225 | // Time to grow the array? | 
|---|
|  | 226 | // | 
|---|
|  | 227 | else if(nthreads_ == threadsLength_) | 
|---|
|  | 228 | { | 
|---|
|  | 229 |  | 
|---|
|  | 230 | // | 
|---|
|  | 231 | // Allocate and then copy.  This is more exception safe. | 
|---|
|  | 232 | // | 
|---|
|  | 233 | int newThreadLength = nthreads_*2; | 
|---|
|  | 234 | JTCThreadHandle* newThreads = new JTCThreadHandle[newThreadLength]; | 
|---|
|  | 235 |  | 
|---|
|  | 236 |  | 
|---|
|  | 237 | // This generates an internal error with gcc 2.7.2 | 
|---|
|  | 238 | //for(int i = 0; i < nthreads_; ++i) | 
|---|
|  | 239 | //{ | 
|---|
|  | 240 | //    newThreads[i] = threads_[i]; | 
|---|
|  | 241 | //} | 
|---|
|  | 242 | // Use this instead | 
|---|
|  | 243 | copy_it(threads_, nthreads_, newThreads); | 
|---|
|  | 244 | // | 
|---|
|  | 245 |  | 
|---|
|  | 246 | // This generates an internal error with gcc 2.7.2 | 
|---|
|  | 247 | //delete[] threads_; | 
|---|
|  | 248 | // Use this instead | 
|---|
|  | 249 | delete_it(threads_); | 
|---|
|  | 250 | // | 
|---|
|  | 251 | threads_ = newThreads; | 
|---|
|  | 252 | threadsLength_ = newThreadLength; | 
|---|
|  | 253 | } | 
|---|
|  | 254 | // | 
|---|
|  | 255 | // Add thread. | 
|---|
|  | 256 | // | 
|---|
|  | 257 | threads_[nthreads_] = t; | 
|---|
|  | 258 | ++nthreads_; | 
|---|
|  | 259 | } | 
|---|
|  | 260 |  | 
|---|
|  | 261 | // | 
|---|
|  | 262 | // Remove a thread from my thread set. | 
|---|
|  | 263 | // | 
|---|
|  | 264 | void | 
|---|
|  | 265 | JTCThreadGroup::remove(JTCThreadHandle t) | 
|---|
|  | 266 | { | 
|---|
|  | 267 | JTCSynchronized sync(*this); | 
|---|
|  | 268 | if(destroyed_) | 
|---|
|  | 269 | { | 
|---|
|  | 270 | throw JTCIllegalThreadStateException(); | 
|---|
|  | 271 | } | 
|---|
|  | 272 | for(int i = 0; i < nthreads_; ++i) | 
|---|
|  | 273 | { | 
|---|
|  | 274 | if(threads_[i] == t) | 
|---|
|  | 275 | { | 
|---|
|  | 276 | --nthreads_; | 
|---|
|  | 277 | for(int j = i; j < nthreads_; ++j) | 
|---|
|  | 278 | { | 
|---|
|  | 279 | threads_[j]  = threads_[j+1]; | 
|---|
|  | 280 | } | 
|---|
|  | 281 | threads_[nthreads_] = JTCThreadHandle(); | 
|---|
|  | 282 | } | 
|---|
|  | 283 | } | 
|---|
|  | 284 | if(nthreads_ == 0) | 
|---|
|  | 285 | { | 
|---|
|  | 286 | notifyAll(); | 
|---|
|  | 287 | } | 
|---|
|  | 288 | if(daemon_ && nthreads_ == 0 && ngroups_ == 0) | 
|---|
|  | 289 | { | 
|---|
|  | 290 | destroy(); | 
|---|
|  | 291 | } | 
|---|
|  | 292 | } | 
|---|
|  | 293 |  | 
|---|
|  | 294 | // | 
|---|
|  | 295 | // TODO:  ensure that exceptions don't cause memory leaks.  Currently | 
|---|
|  | 296 | // exceptions can cause the GroupSnapshot to be trashed.  Some sort | 
|---|
|  | 297 | // of auto_ptr can fix this. | 
|---|
|  | 298 | // | 
|---|
|  | 299 |  | 
|---|
|  | 300 | // | 
|---|
|  | 301 | // Copy threads from my thread set into the provided array. | 
|---|
|  | 302 | // | 
|---|
|  | 303 | int | 
|---|
|  | 304 | JTCThreadGroup::enumerate(JTCThreadHandle* list, int len, int n, | 
|---|
|  | 305 | bool recurse) const | 
|---|
|  | 306 | { | 
|---|
|  | 307 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 308 |  | 
|---|
|  | 309 | { | 
|---|
|  | 310 | JTCSynchronized sync(*this); | 
|---|
|  | 311 |  | 
|---|
|  | 312 | if(destroyed_) | 
|---|
|  | 313 | { | 
|---|
|  | 314 | return 0; | 
|---|
|  | 315 | } | 
|---|
|  | 316 |  | 
|---|
|  | 317 | // | 
|---|
|  | 318 | // Copy threads into the provided list. | 
|---|
|  | 319 | // | 
|---|
|  | 320 | int nt = nthreads_; | 
|---|
|  | 321 | if(nt > len - n) | 
|---|
|  | 322 | { | 
|---|
|  | 323 | nt = len - n; | 
|---|
|  | 324 | } | 
|---|
|  | 325 | if(nt > 0) | 
|---|
|  | 326 | { | 
|---|
|  | 327 | for(int i = 0; i < nt; ++i) | 
|---|
|  | 328 | { | 
|---|
|  | 329 | list[i+n] = threads_[i]; | 
|---|
|  | 330 | } | 
|---|
|  | 331 | n += nt; | 
|---|
|  | 332 | } | 
|---|
|  | 333 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 334 | } | 
|---|
|  | 335 |  | 
|---|
|  | 336 | // | 
|---|
|  | 337 | // Recurse into child ThreadGroups? | 
|---|
|  | 338 | // | 
|---|
|  | 339 | if(recurse) | 
|---|
|  | 340 | { | 
|---|
|  | 341 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 342 | { | 
|---|
|  | 343 | n = groupsSnapshot[i] -> enumerate(list, len, n, 1); | 
|---|
|  | 344 | } | 
|---|
|  | 345 | } | 
|---|
|  | 346 |  | 
|---|
|  | 347 | return n; | 
|---|
|  | 348 | } | 
|---|
|  | 349 |  | 
|---|
|  | 350 | // | 
|---|
|  | 351 | // Copy the set of ThreadGroups into the provided array. | 
|---|
|  | 352 | // | 
|---|
|  | 353 | int | 
|---|
|  | 354 | JTCThreadGroup::enumerate(JTCThreadGroupHandle* list, int len, int n, | 
|---|
|  | 355 | bool recurse) const | 
|---|
|  | 356 | { | 
|---|
|  | 357 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 358 |  | 
|---|
|  | 359 | { | 
|---|
|  | 360 | JTCSynchronized sync(*this); | 
|---|
|  | 361 |  | 
|---|
|  | 362 | if(destroyed_) | 
|---|
|  | 363 | { | 
|---|
|  | 364 | return 0; | 
|---|
|  | 365 | } | 
|---|
|  | 366 |  | 
|---|
|  | 367 | int ng = nthreads_; | 
|---|
|  | 368 | if(ng > len - n) | 
|---|
|  | 369 | { | 
|---|
|  | 370 | ng = len - n; | 
|---|
|  | 371 | } | 
|---|
|  | 372 | if(ng > 0) | 
|---|
|  | 373 | { | 
|---|
|  | 374 | for(int i = 0; i < ng; ++i) | 
|---|
|  | 375 | { | 
|---|
|  | 376 | list[i+n] = groups_[i]; | 
|---|
|  | 377 | } | 
|---|
|  | 378 | n += ng; | 
|---|
|  | 379 | } | 
|---|
|  | 380 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 381 | } | 
|---|
|  | 382 |  | 
|---|
|  | 383 | // | 
|---|
|  | 384 | // Recurse into child ThreadGroups? | 
|---|
|  | 385 | // | 
|---|
|  | 386 | if(recurse) | 
|---|
|  | 387 | { | 
|---|
|  | 388 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 389 | { | 
|---|
|  | 390 | n = groupsSnapshot[i] -> enumerate(list, len, n, 1); | 
|---|
|  | 391 | } | 
|---|
|  | 392 | } | 
|---|
|  | 393 |  | 
|---|
|  | 394 | return n; | 
|---|
|  | 395 | } | 
|---|
|  | 396 |  | 
|---|
|  | 397 | // | 
|---|
|  | 398 | // Constructor helper. | 
|---|
|  | 399 | // | 
|---|
|  | 400 | void | 
|---|
|  | 401 | JTCThreadGroup::init(JTCThreadGroup* parent, const char* n) | 
|---|
|  | 402 | { | 
|---|
|  | 403 | // | 
|---|
|  | 404 | // Initialize state variables. | 
|---|
|  | 405 | // | 
|---|
|  | 406 | ngroups_ = 0; | 
|---|
|  | 407 | groups_ = 0; | 
|---|
|  | 408 | groupsLength_ = 0; | 
|---|
|  | 409 | nthreads_ = 0; | 
|---|
|  | 410 | threads_ = 0; | 
|---|
|  | 411 | threadsLength_ = 0; | 
|---|
|  | 412 | destroyed_ = false; | 
|---|
|  | 413 | daemon_ = parent -> daemon_; | 
|---|
|  | 414 |  | 
|---|
|  | 415 | // | 
|---|
|  | 416 | // Copy name. | 
|---|
|  | 417 | // | 
|---|
|  | 418 | name_ = new char[strlen(n)+1]; | 
|---|
|  | 419 | strcpy(name_, n); | 
|---|
|  | 420 |  | 
|---|
|  | 421 | maxPriority_ = parent -> maxPriority_; | 
|---|
|  | 422 |  | 
|---|
|  | 423 | // | 
|---|
|  | 424 | // Add myself to my parent. | 
|---|
|  | 425 | // | 
|---|
|  | 426 | parent_ = parent; | 
|---|
|  | 427 | parent -> add(this); | 
|---|
|  | 428 | } | 
|---|
|  | 429 |  | 
|---|
|  | 430 | // ---------------------------------------------------------------------- | 
|---|
|  | 431 | // JTCThreadGroup private constructor | 
|---|
|  | 432 | // ---------------------------------------------------------------------- | 
|---|
|  | 433 |  | 
|---|
|  | 434 | // | 
|---|
|  | 435 | // This is the constructor that creates the main thread group. | 
|---|
|  | 436 | // | 
|---|
|  | 437 | JTCThreadGroup::JTCThreadGroup(bool main) | 
|---|
|  | 438 | : parent_(0), | 
|---|
|  | 439 | destroyed_(false), | 
|---|
|  | 440 | nthreads_(0), | 
|---|
|  | 441 | threads_(0), | 
|---|
|  | 442 | threadsLength_(0), | 
|---|
|  | 443 | ngroups_(0), | 
|---|
|  | 444 | groups_(0), | 
|---|
|  | 445 | groupsLength_(0), | 
|---|
|  | 446 | daemon_(false) | 
|---|
|  | 447 | { | 
|---|
|  | 448 | // | 
|---|
|  | 449 | // Default name of the system ThreadGroup is system, otherwise | 
|---|
|  | 450 | // the name is adopted. | 
|---|
|  | 451 | // | 
|---|
|  | 452 | const char* defaultName = (main) ? "system" : "adopted"; | 
|---|
|  | 453 | name_ = new char[strlen(defaultName)+1]; | 
|---|
|  | 454 | strcpy(name_, defaultName); | 
|---|
|  | 455 |  | 
|---|
|  | 456 | maxPriority_ = JTCThread::JTC_MAX_PRIORITY; | 
|---|
|  | 457 | } | 
|---|
|  | 458 |  | 
|---|
|  | 459 | // ---------------------------------------------------------------------- | 
|---|
|  | 460 | // JTCThreadGroup constructors and destructor | 
|---|
|  | 461 | // ---------------------------------------------------------------------- | 
|---|
|  | 462 |  | 
|---|
|  | 463 | JTCThreadGroup::JTCThreadGroup(const char* name) | 
|---|
|  | 464 | { | 
|---|
|  | 465 | init(JTCThread::currentThread() -> getThreadGroup().get(), name); | 
|---|
|  | 466 | } | 
|---|
|  | 467 |  | 
|---|
|  | 468 | JTCThreadGroup::JTCThreadGroup(JTCThreadGroup* parent, const char* name) | 
|---|
|  | 469 | { | 
|---|
|  | 470 | init(parent, name); | 
|---|
|  | 471 | } | 
|---|
|  | 472 |  | 
|---|
|  | 473 | JTCThreadGroup::~JTCThreadGroup() | 
|---|
|  | 474 | { | 
|---|
|  | 475 | try | 
|---|
|  | 476 | { | 
|---|
|  | 477 | JTCSynchronized sync(*this); | 
|---|
|  | 478 | if (!destroyed_) | 
|---|
|  | 479 | { | 
|---|
|  | 480 | destroy(); | 
|---|
|  | 481 | } | 
|---|
|  | 482 | } | 
|---|
|  | 483 | catch(const JTCIllegalThreadStateException&) | 
|---|
|  | 484 | { | 
|---|
|  | 485 | cerr << "Unexpected JTCIllegalThreadStateException in ~JTCThreadGroup" | 
|---|
|  | 486 | << endl; | 
|---|
|  | 487 | } | 
|---|
|  | 488 | delete[] name_; | 
|---|
|  | 489 | } | 
|---|
|  | 490 |  | 
|---|
|  | 491 | // ---------------------------------------------------------------------- | 
|---|
|  | 492 | // JTCThreadGroup public member implementation | 
|---|
|  | 493 | // ---------------------------------------------------------------------- | 
|---|
|  | 494 |  | 
|---|
|  | 495 | // | 
|---|
|  | 496 | // Return name of the this ThreadGroup. | 
|---|
|  | 497 | // | 
|---|
|  | 498 | const char* | 
|---|
|  | 499 | JTCThreadGroup::getName() const | 
|---|
|  | 500 | { | 
|---|
|  | 501 | return name_; | 
|---|
|  | 502 | } | 
|---|
|  | 503 |  | 
|---|
|  | 504 | // | 
|---|
|  | 505 | // Return the parent of this ThreadGroup. | 
|---|
|  | 506 | // | 
|---|
|  | 507 | JTCThreadGroupHandle | 
|---|
|  | 508 | JTCThreadGroup::getParent() const | 
|---|
|  | 509 | { | 
|---|
|  | 510 | return JTCThreadGroupHandle(parent_); | 
|---|
|  | 511 | } | 
|---|
|  | 512 |  | 
|---|
|  | 513 | // | 
|---|
|  | 514 | // Is this a daemon ThreadGroup? | 
|---|
|  | 515 | // | 
|---|
|  | 516 | bool | 
|---|
|  | 517 | JTCThreadGroup::isDaemon() const | 
|---|
|  | 518 | { | 
|---|
|  | 519 | return daemon_; | 
|---|
|  | 520 | } | 
|---|
|  | 521 |  | 
|---|
|  | 522 | // | 
|---|
|  | 523 | // Set the daemon ThreadGroup flag. | 
|---|
|  | 524 | // | 
|---|
|  | 525 |  | 
|---|
|  | 526 | void | 
|---|
|  | 527 | JTCThreadGroup::setDaemon(bool daemon) | 
|---|
|  | 528 | { | 
|---|
|  | 529 | daemon_ = daemon; | 
|---|
|  | 530 | } | 
|---|
|  | 531 |  | 
|---|
|  | 532 | // | 
|---|
|  | 533 | // Called on an uncaught exception. | 
|---|
|  | 534 | // | 
|---|
|  | 535 | void | 
|---|
|  | 536 | JTCThreadGroup::uncaughtException(JTCThreadHandle t, const JTCException& e) | 
|---|
|  | 537 | { | 
|---|
|  | 538 | if (parent_) | 
|---|
|  | 539 | { | 
|---|
|  | 540 | parent_ -> uncaughtException(t, e); | 
|---|
|  | 541 | } | 
|---|
|  | 542 | else | 
|---|
|  | 543 | { | 
|---|
|  | 544 | cerr << e << endl; | 
|---|
|  | 545 | } | 
|---|
|  | 546 | } | 
|---|
|  | 547 |  | 
|---|
|  | 548 | // | 
|---|
|  | 549 | // Called on an uncaught exception (... style) | 
|---|
|  | 550 | // | 
|---|
|  | 551 | void | 
|---|
|  | 552 | JTCThreadGroup::uncaughtException(JTCThreadHandle t) | 
|---|
|  | 553 | { | 
|---|
|  | 554 | if (parent_) | 
|---|
|  | 555 | { | 
|---|
|  | 556 | parent_ -> uncaughtException(t); | 
|---|
|  | 557 | } | 
|---|
|  | 558 | else | 
|---|
|  | 559 | { | 
|---|
|  | 560 | cerr << "unknown exception" << endl; | 
|---|
|  | 561 | } | 
|---|
|  | 562 | } | 
|---|
|  | 563 |  | 
|---|
|  | 564 | // | 
|---|
|  | 565 | // Return the maximum priority of this ThreadGroup. | 
|---|
|  | 566 | // | 
|---|
|  | 567 | int | 
|---|
|  | 568 | JTCThreadGroup::getMaxPriority() const | 
|---|
|  | 569 | { | 
|---|
|  | 570 | return maxPriority_; | 
|---|
|  | 571 | } | 
|---|
|  | 572 |  | 
|---|
|  | 573 | #ifdef HAVE_JTC_STOP | 
|---|
|  | 574 | // | 
|---|
|  | 575 | // Stop all threads in this ThreadGroup, and child ThreadGroups. | 
|---|
|  | 576 | // | 
|---|
|  | 577 | void | 
|---|
|  | 578 | JTCThreadGroup::stop() | 
|---|
|  | 579 | { | 
|---|
|  | 580 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 581 |  | 
|---|
|  | 582 | { | 
|---|
|  | 583 | JTCSynchronized sync(*this); | 
|---|
|  | 584 |  | 
|---|
|  | 585 | // | 
|---|
|  | 586 | // Stop all of the threads that this ThreadGroup owns. | 
|---|
|  | 587 | // | 
|---|
|  | 588 | for (int i = 0; i < nthreads_; ++i) | 
|---|
|  | 589 | { | 
|---|
|  | 590 | threads_[i] -> stop(); | 
|---|
|  | 591 | } | 
|---|
|  | 592 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 593 | } | 
|---|
|  | 594 |  | 
|---|
|  | 595 | // | 
|---|
|  | 596 | // Ask each child ThreadGroup to stop their threads. | 
|---|
|  | 597 | // | 
|---|
|  | 598 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 599 | { | 
|---|
|  | 600 | groupsSnapshot[i] -> stop(); | 
|---|
|  | 601 | } | 
|---|
|  | 602 | } | 
|---|
|  | 603 |  | 
|---|
|  | 604 | // | 
|---|
|  | 605 | // Resume all threads in our ThreadGroup, and child ThreadGroups. | 
|---|
|  | 606 | // | 
|---|
|  | 607 | void | 
|---|
|  | 608 | JTCThreadGroup::resume() | 
|---|
|  | 609 | { | 
|---|
|  | 610 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 611 |  | 
|---|
|  | 612 | { | 
|---|
|  | 613 | JTCSynchronized sync(*this); | 
|---|
|  | 614 | // | 
|---|
|  | 615 | // Resume all threads in our ThreadGroup. | 
|---|
|  | 616 | // | 
|---|
|  | 617 | for (int i = 0; i < nthreads_; ++i) | 
|---|
|  | 618 | { | 
|---|
|  | 619 | threads_[i] -> resume(); | 
|---|
|  | 620 | } | 
|---|
|  | 621 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 622 | } | 
|---|
|  | 623 |  | 
|---|
|  | 624 | // | 
|---|
|  | 625 | // Resume all threads in our child ThreadGroups. | 
|---|
|  | 626 | // | 
|---|
|  | 627 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 628 | { | 
|---|
|  | 629 | groupsSnapshot[i] -> resume(); | 
|---|
|  | 630 | } | 
|---|
|  | 631 | } | 
|---|
|  | 632 |  | 
|---|
|  | 633 | // | 
|---|
|  | 634 | // Suspend all threads in our ThreadGroup, and child ThreadGroups. | 
|---|
|  | 635 | // | 
|---|
|  | 636 | void | 
|---|
|  | 637 | JTCThreadGroup::suspend() | 
|---|
|  | 638 | { | 
|---|
|  | 639 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 640 |  | 
|---|
|  | 641 | { | 
|---|
|  | 642 | JTCSynchronized sync(*this); | 
|---|
|  | 643 |  | 
|---|
|  | 644 | // | 
|---|
|  | 645 | // Suspend all threads in our ThreadGroup. | 
|---|
|  | 646 | // | 
|---|
|  | 647 | for (int i = 0; i < nthreads_; ++i) | 
|---|
|  | 648 | { | 
|---|
|  | 649 | threads_[i] -> suspend(); | 
|---|
|  | 650 | } | 
|---|
|  | 651 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 652 | } | 
|---|
|  | 653 |  | 
|---|
|  | 654 | // | 
|---|
|  | 655 | // Suspend all threads in our child ThreadGroups. | 
|---|
|  | 656 | // | 
|---|
|  | 657 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 658 | { | 
|---|
|  | 659 | groupsSnapshot[i] -> suspend(); | 
|---|
|  | 660 | } | 
|---|
|  | 661 | } | 
|---|
|  | 662 | #endif | 
|---|
|  | 663 |  | 
|---|
|  | 664 | // | 
|---|
|  | 665 | // Has this ThreadGroup been destroyed? | 
|---|
|  | 666 | // | 
|---|
|  | 667 | bool | 
|---|
|  | 668 | JTCThreadGroup::isDestroyed() const | 
|---|
|  | 669 | { | 
|---|
|  | 670 | JTCSynchronized sync(*this); | 
|---|
|  | 671 | return destroyed_; | 
|---|
|  | 672 | } | 
|---|
|  | 673 |  | 
|---|
|  | 674 | // | 
|---|
|  | 675 | // Destroy this ThreadGroup. | 
|---|
|  | 676 | // | 
|---|
|  | 677 | void | 
|---|
|  | 678 | JTCThreadGroup::destroy() | 
|---|
|  | 679 | { | 
|---|
|  | 680 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 681 |  | 
|---|
|  | 682 | { | 
|---|
|  | 683 | JTCSynchronized sync(*this); | 
|---|
|  | 684 | if(destroyed_ || nthreads_ > 0) | 
|---|
|  | 685 | { | 
|---|
|  | 686 | throw JTCIllegalThreadStateException(); | 
|---|
|  | 687 | } | 
|---|
|  | 688 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 689 |  | 
|---|
|  | 690 | destroyed_ = true; | 
|---|
|  | 691 | ngroups_ = 0; | 
|---|
|  | 692 | delete[] groups_; | 
|---|
|  | 693 | groups_ = 0; | 
|---|
|  | 694 | groupsLength_ = 0; | 
|---|
|  | 695 | nthreads_ = 0; | 
|---|
|  | 696 | delete[] threads_; | 
|---|
|  | 697 | threads_ = 0; | 
|---|
|  | 698 | threadsLength_ = 0; | 
|---|
|  | 699 | } | 
|---|
|  | 700 |  | 
|---|
|  | 701 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 702 | { | 
|---|
|  | 703 | groupsSnapshot[i] -> destroy(); | 
|---|
|  | 704 | } | 
|---|
|  | 705 |  | 
|---|
|  | 706 | if(parent_) | 
|---|
|  | 707 | { | 
|---|
|  | 708 | parent_ -> remove(this); | 
|---|
|  | 709 | } | 
|---|
|  | 710 | } | 
|---|
|  | 711 |  | 
|---|
|  | 712 | // | 
|---|
|  | 713 | // Set maximum priority value for this ThreadGroup, and our child | 
|---|
|  | 714 | // ThreadGroups. | 
|---|
|  | 715 | // | 
|---|
|  | 716 | void | 
|---|
|  | 717 | JTCThreadGroup::setMaxPriority(int pri) | 
|---|
|  | 718 | { | 
|---|
|  | 719 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 720 |  | 
|---|
|  | 721 | { | 
|---|
|  | 722 | JTCSynchronized sync(*this); | 
|---|
|  | 723 | if(pri < JTCThread::JTC_MIN_PRIORITY) | 
|---|
|  | 724 | { | 
|---|
|  | 725 | maxPriority_ = JTCThread::JTC_MIN_PRIORITY; | 
|---|
|  | 726 | } | 
|---|
|  | 727 | else if(pri < maxPriority_) | 
|---|
|  | 728 | { | 
|---|
|  | 729 | maxPriority_ = pri; | 
|---|
|  | 730 | } | 
|---|
|  | 731 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 732 | } | 
|---|
|  | 733 |  | 
|---|
|  | 734 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 735 | { | 
|---|
|  | 736 | groupsSnapshot[i] -> setMaxPriority(pri); | 
|---|
|  | 737 | } | 
|---|
|  | 738 | } | 
|---|
|  | 739 |  | 
|---|
|  | 740 | // | 
|---|
|  | 741 | // Is this ThreadGroup a parent of handle? | 
|---|
|  | 742 | // | 
|---|
|  | 743 | bool | 
|---|
|  | 744 | JTCThreadGroup::parentOf(JTCThreadGroupHandle handle) | 
|---|
|  | 745 | { | 
|---|
|  | 746 | JTCThreadGroup* g = handle.get(); | 
|---|
|  | 747 | for(;g != 0; g = g -> parent_.get()) | 
|---|
|  | 748 | { | 
|---|
|  | 749 | if(g == this) | 
|---|
|  | 750 | { | 
|---|
|  | 751 | return true; | 
|---|
|  | 752 | } | 
|---|
|  | 753 | } | 
|---|
|  | 754 | return false; | 
|---|
|  | 755 | } | 
|---|
|  | 756 |  | 
|---|
|  | 757 | // | 
|---|
|  | 758 | // Determine the number of active threads in this ThreadGroup, and | 
|---|
|  | 759 | // child ThreadGroups. | 
|---|
|  | 760 | // | 
|---|
|  | 761 | int | 
|---|
|  | 762 | JTCThreadGroup::activeCount() const | 
|---|
|  | 763 | { | 
|---|
|  | 764 | int result = 0; | 
|---|
|  | 765 |  | 
|---|
|  | 766 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 767 |  | 
|---|
|  | 768 | { | 
|---|
|  | 769 | JTCSynchronized sync(*this); | 
|---|
|  | 770 |  | 
|---|
|  | 771 | if(destroyed_) | 
|---|
|  | 772 | { | 
|---|
|  | 773 | return 0; | 
|---|
|  | 774 | } | 
|---|
|  | 775 | result = nthreads_; | 
|---|
|  | 776 |  | 
|---|
|  | 777 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 778 | } | 
|---|
|  | 779 |  | 
|---|
|  | 780 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 781 | { | 
|---|
|  | 782 | result += groupsSnapshot[i] -> activeCount(); | 
|---|
|  | 783 | } | 
|---|
|  | 784 |  | 
|---|
|  | 785 | return result; | 
|---|
|  | 786 | } | 
|---|
|  | 787 |  | 
|---|
|  | 788 | // | 
|---|
|  | 789 | // Determine the number of ThreadGroups in this group, and child | 
|---|
|  | 790 | // ThreadGroups. | 
|---|
|  | 791 | // | 
|---|
|  | 792 | int | 
|---|
|  | 793 | JTCThreadGroup::activeGroupCount() const | 
|---|
|  | 794 | { | 
|---|
|  | 795 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 796 |  | 
|---|
|  | 797 | { | 
|---|
|  | 798 | JTCSynchronized sync(*this); | 
|---|
|  | 799 |  | 
|---|
|  | 800 | if(destroyed_) | 
|---|
|  | 801 | { | 
|---|
|  | 802 | return 0; | 
|---|
|  | 803 | } | 
|---|
|  | 804 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 805 | } | 
|---|
|  | 806 |  | 
|---|
|  | 807 | int n = groupsSnapshot.length(); | 
|---|
|  | 808 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 809 | { | 
|---|
|  | 810 | n += groupsSnapshot[i] -> activeCount(); | 
|---|
|  | 811 | } | 
|---|
|  | 812 | return n; | 
|---|
|  | 813 | } | 
|---|
|  | 814 |  | 
|---|
|  | 815 | // | 
|---|
|  | 816 | // Copy the set of threads in this ThreadGroup, and child ThreadGroups | 
|---|
|  | 817 | // if recurse is true into array list. | 
|---|
|  | 818 | // | 
|---|
|  | 819 | int | 
|---|
|  | 820 | JTCThreadGroup::enumerate(JTCThreadHandle* list, int len, bool recurse) const | 
|---|
|  | 821 | { | 
|---|
|  | 822 | return enumerate(list, len, 0, recurse); | 
|---|
|  | 823 | } | 
|---|
|  | 824 |  | 
|---|
|  | 825 | // | 
|---|
|  | 826 | // Copy the set child ThreadGroups in this ThreadGroup, and child ThreadGroups | 
|---|
|  | 827 | // if recurse is true into array list. | 
|---|
|  | 828 | // | 
|---|
|  | 829 | int | 
|---|
|  | 830 | JTCThreadGroup::enumerate(JTCThreadGroupHandle* list, int len, | 
|---|
|  | 831 | bool recurse) const | 
|---|
|  | 832 | { | 
|---|
|  | 833 | return enumerate(list, len, 0, recurse); | 
|---|
|  | 834 | } | 
|---|
|  | 835 |  | 
|---|
|  | 836 | // | 
|---|
|  | 837 | // Display set of threads and ThreadGroups to cout. | 
|---|
|  | 838 | // | 
|---|
|  | 839 | void | 
|---|
|  | 840 | JTCThreadGroup::list() | 
|---|
|  | 841 | { | 
|---|
|  | 842 | list(cout, 0); | 
|---|
|  | 843 | } | 
|---|
|  | 844 |  | 
|---|
|  | 845 | // | 
|---|
|  | 846 | // Display the set of threads and ThreadGroups to os, with given indent | 
|---|
|  | 847 | // level. | 
|---|
|  | 848 | // | 
|---|
|  | 849 | void | 
|---|
|  | 850 | JTCThreadGroup::list(ostream& os, int indent) | 
|---|
|  | 851 | { | 
|---|
|  | 852 | JTCThreadGroupSet groupsSnapshot; | 
|---|
|  | 853 |  | 
|---|
|  | 854 | { | 
|---|
|  | 855 | JTCSynchronized sync(*this); | 
|---|
|  | 856 | for(int j = 0; j < indent; ++j) | 
|---|
|  | 857 | { | 
|---|
|  | 858 | os << " "; | 
|---|
|  | 859 | } | 
|---|
|  | 860 | os << *this << endl; | 
|---|
|  | 861 | indent += 4; | 
|---|
|  | 862 | for(int i = 0; i < nthreads_; ++i) | 
|---|
|  | 863 | { | 
|---|
|  | 864 | for(int i_level = 0; i_level < indent; ++i_level) | 
|---|
|  | 865 | { | 
|---|
|  | 866 | os << " "; | 
|---|
|  | 867 | } | 
|---|
|  | 868 | os << *threads_[i] << endl; | 
|---|
|  | 869 | } | 
|---|
|  | 870 | createGroupSnapshot(groupsSnapshot); | 
|---|
|  | 871 | } | 
|---|
|  | 872 | for(int i = 0; i < groupsSnapshot.length(); ++i) | 
|---|
|  | 873 | { | 
|---|
|  | 874 | groupsSnapshot[i] -> list(os, indent); | 
|---|
|  | 875 | } | 
|---|
|  | 876 | } | 
|---|
|  | 877 |  | 
|---|
|  | 878 | // | 
|---|
|  | 879 | // IOstream insertion operator for a ThreadGroup. | 
|---|
|  | 880 | // | 
|---|
|  | 881 | ostream& | 
|---|
|  | 882 | operator<<(ostream& os, const JTCThreadGroup& g) | 
|---|
|  | 883 | { | 
|---|
|  | 884 | os << "ThreadGroup: " | 
|---|
|  | 885 | << "[name=" << g.getName() << ",maxpri=" << g.getMaxPriority() << "]"; | 
|---|
|  | 886 | return os; | 
|---|
|  | 887 | } | 
|---|