1 karl 1.44 //%2005////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
|
3 karl 1.42 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.34 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.42 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.44 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 mike 1.2 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 kumpf 1.18 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
16 mike 1.2 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
|
19 kumpf 1.18 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
20 mike 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
22 kumpf 1.18 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
25 mike 1.2 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Mike Day (mdday@us.ibm.com)
31 //
32 // Modified By: Markus Mueller
|
33 kumpf 1.36 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
34 a.arora 1.37 // Amit K Arora, IBM (amita@in.ibm.com) for PEP#101
|
35 david.dillard 1.43 // David Dillard, VERITAS Software Corp.
36 // (david.dillard@veritas.com)
|
37 gs.keenan 1.45 // Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com)
|
38 joyce.j 1.51 // Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#2393
|
39 mike 1.2 //
40 //%/////////////////////////////////////////////////////////////////////////////
41
42 #ifndef Pegasus_Thread_h
43 #define Pegasus_Thread_h
|
44 kumpf 1.26
45 #include <cstring>
|
46 mike 1.2 #include <Pegasus/Common/Config.h>
|
47 mike 1.5 #include <Pegasus/Common/IPC.h>
|
48 kumpf 1.23 #include <Pegasus/Common/InternalException.h>
|
49 mike 1.2 #include <Pegasus/Common/DQueue.h>
|
50 a.dunfey 1.53.12.1 #include <Pegasus/Common/AcceptLanguageList.h>
|
51 kumpf 1.22 #include <Pegasus/Common/Linkage.h>
|
52 a.arora 1.37 #include <Pegasus/Common/AutoPtr.h>
|
53 mike 1.2
54 PEGASUS_NAMESPACE_BEGIN
55
56 class PEGASUS_COMMON_LINKAGE cleanup_handler
57 {
58
59 public:
60 cleanup_handler( void (*routine)(void *), void *arg ) : _routine(routine), _arg(arg) {}
61 ~cleanup_handler() {; }
62 inline Boolean operator==(const void *key) const
|
63 kumpf 1.48 {
64 if(key == (void *)_routine)
65 return true;
66 return false;
|
67 mike 1.2 }
|
68 kumpf 1.48 inline Boolean operator ==(const cleanup_handler & b) const
|
69 mike 1.2 {
|
70 kumpf 1.48 return(operator==((const void *)b._routine));
|
71 mike 1.2 }
72 private:
|
73 david.dillard 1.50 void execute() { _routine(_arg); }
|
74 mike 1.2 cleanup_handler();
75 void (*_routine)(void *);
76
|
77 kumpf 1.48 void *_arg;
|
78 mike 1.2 PEGASUS_CLEANUP_HANDLE _cleanup_buffer;
79 friend class DQueue<class cleanup_handler>;
80 friend class Thread;
81 };
82
83 ///////////////////////////////////////////////////////////////////////////////
84
85
86 class PEGASUS_COMMON_LINKAGE thread_data
87 {
88
89 public:
90 static void default_delete(void *data);
|
91 kumpf 1.48
|
92 david.dillard 1.43 thread_data( const char *key ) : _delete_func(NULL) , _data(NULL), _size(0)
|
93 mike 1.2 {
|
94 kumpf 1.48 PEGASUS_ASSERT(key != NULL);
95 size_t keysize = strlen(key);
|
96 joyce.j 1.51 _key.reset(new char[keysize + 1]);
97 memcpy(_key.get(), key, keysize);
98 _key.get()[keysize] = 0x00;
|
99 kumpf 1.48
|
100 mike 1.2 }
|
101 kumpf 1.48
|
102 david.dillard 1.43 thread_data(const char *key, size_t size) : _delete_func(default_delete), _size(size)
|
103 mike 1.2 {
|
104 kumpf 1.48 PEGASUS_ASSERT(key != NULL);
105 size_t keysize = strlen(key);
|
106 joyce.j 1.51 _key.reset(new char[keysize + 1]);
107 memcpy(_key.get(), key, keysize);
108 _key.get()[keysize] = 0x00;
|
109 david.dillard 1.50 _data = ::operator new(_size);
|
110 mike 1.2
111 }
112
|
113 david.dillard 1.43 thread_data(const char *key, size_t size, void *data) : _delete_func(default_delete), _size(size)
|
114 mike 1.2 {
|
115 kumpf 1.48 PEGASUS_ASSERT(key != NULL);
116 PEGASUS_ASSERT(data != NULL);
117 size_t keysize = strlen(key);
118
|
119 joyce.j 1.51 _key.reset(new char[keysize + 1]);
120 memcpy(_key.get(), key, keysize);
121 _key.get()[keysize] = 0x00;
|
122 kumpf 1.48 _data = ::operator new(_size);
123 memcpy(_data, data, size);
|
124 mike 1.2 }
125
|
126 kumpf 1.48 ~thread_data()
127 {
128 if( _data != NULL)
129 if(_delete_func != NULL)
|
130 sage 1.9 {
|
131 kumpf 1.48 _delete_func( _data );
|
132 sage 1.9 }
|
133 kumpf 1.48 }
|
134 mike 1.2
|
135 konrad.r 1.40 /**
136 * This function is used to put data in thread space.
137 *
|
138 kumpf 1.48 * Be aware that there is NOTHING in place to stop
139 * other users of the thread to remove this data.
|
140 konrad.r 1.40 * Or change the data.
141 *
|
142 kumpf 1.48 * You, the developer has to make sure that there are
143 * no situations in which this can arise (ie, have a
|
144 konrad.r 1.40 * lock for the function which manipulates the TSD.
|
145 david.dillard 1.50 *
146 * @exception NullPointer
|
147 konrad.r 1.40 */
|
148 david.dillard 1.50 void put_data(void (*del)(void *), size_t size, void *data )
|
149 mike 1.2 {
|
150 kumpf 1.48 if(_data != NULL)
151 if(_delete_func != NULL)
152 _delete_func(_data);
153
154 _delete_func = del;
155 _data = data;
156 _size = size;
|
157 david.dillard 1.50 return;
|
158 mike 1.2 }
159
|
160 david.dillard 1.50 size_t get_size() { return _size; }
|
161 mike 1.2
|
162 konrad.r 1.40 /**
|
163 kumpf 1.48 * This function is used to retrieve data from the
164 * TSD, the thread specific data.
|
165 konrad.r 1.40 *
|
166 kumpf 1.48 * Be aware that there is NOTHING in place to stop
|
167 konrad.r 1.40 * other users of the thread to change the data you
168 * get from this function.
169 *
|
170 kumpf 1.48 * You, the developer has to make sure that there are
171 * no situations in which this can arise (ie, have a
|
172 konrad.r 1.40 * lock for the function which manipulates the TSD.
173 */
|
174 kumpf 1.48 void get_data(void **data, size_t *size)
175 {
176 if(data == NULL || size == NULL)
177 throw NullPointer();
178
179 *data = _data;
180 *size = _size;
181 return;
182
|
183 mike 1.2 }
184
|
185 david.dillard 1.50 // @exception NullPointer
186 void copy_data(void **buf, size_t *size)
|
187 mike 1.2 {
|
188 kumpf 1.48 if((buf == NULL) || (size == NULL))
|
189 david.dillard 1.50 throw NullPointer();
|
190 kumpf 1.48 *buf = ::operator new(_size);
191 *size = _size;
192 memcpy(*buf, _data, _size);
193 return;
194 }
195
196 inline Boolean operator==(const void *key) const
197 {
|
198 joyce.j 1.52 if ( ! strcmp(_key.get(), reinterpret_cast<const char *>(key)))
|
199 kumpf 1.48 return(true);
200 return(false);
201 }
|
202 mday 1.8
|
203 mike 1.2 inline Boolean operator==(const thread_data& b) const
204 {
|
205 joyce.j 1.51 return(operator==(b._key.get()));
|
206 mike 1.2 }
207
208 private:
|
209 david.dillard 1.50 void (*_delete_func) (void *data);
|
210 mike 1.2 thread_data();
211 void *_data;
212 size_t _size;
|
213 joyce.j 1.51 AutoArrayPtr<char> _key;
|
214 mike 1.2
215 friend class DQueue<thread_data>;
216 friend class Thread;
217 };
218
219
|
220 konrad.r 1.53 enum ThreadStatus {
221 PEGASUS_THREAD_OK = 1, /* No problems */
222 PEGASUS_THREAD_INSUFFICIENT_RESOURCES, /* Can't allocate a thread. Not enough
223 memory. Try again later */
224 PEGASUS_THREAD_SETUP_FAILURE, /* Could not allocate into the thread specific
225 data storage. */
226 PEGASUS_THREAD_UNAVAILABLE /* Service is being destroyed and no new threads can
227 be provided. */
228 };
229
|
230 mike 1.2 ///////////////////////////////////////////////////////////////////////////
231
232 class PEGASUS_COMMON_LINKAGE Thread
233 {
|
234 konrad.r 1.53 public:
|
235 mike 1.2
236 Thread( PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *start )(void *),
|
237 kumpf 1.48 void *parameter, Boolean detached );
|
238 mike 1.2
239 ~Thread();
240
|
241 kumpf 1.36 /**
242 Start the thread.
|
243 konrad.r 1.53 @return PEGASUS_THREAD_OK if the thread is started successfully,
244 PEGASUS_THREAD_INSUFFICIENT_RESOURCES if the resources necessary
245 to start the thread are not currently available.
246 PEGASUS_THREAD_SETUP_FAILURE if the thread could not
247 be create properly - check the 'errno' value for specific operating
248 system return code.
|
249 kumpf 1.36 */
|
250 konrad.r 1.53 ThreadStatus run();
|
251 mike 1.2
|
252 kumpf 1.48 // get the user parameter
|
253 david.dillard 1.50 inline void *get_parm() { return _thread_parm; }
|
254 mike 1.2
255 // cancellation must be deferred (not asynchronous)
256 // for user-level threads the thread itself can decide
|
257 kumpf 1.48 // when it should die.
|
258 david.dillard 1.50 void cancel();
|
259 mike 1.2
260 // cancel if there is a pending cancellation request
|
261 david.dillard 1.50 void test_cancel();
|
262 mike 1.2
|
263 david.dillard 1.50 Boolean is_cancelled();
|
264 kumpf 1.48
|
265 mike 1.2 // for user-level threads - put the calling thread
|
266 kumpf 1.48 // to sleep and jump to the thread scheduler.
267 // platforms with preemptive scheduling and native threads
268 // can define this to be a no-op.
269 // platforms without preemptive scheduling like NetWare
270 // or gnu portable threads will have an existing
271 // routine that can be mapped to this method
|
272 mike 1.2
|
273 david.dillard 1.50 void thread_switch();
|
274 mike 1.2
|
275 david.eger 1.27 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)
|
276 kumpf 1.48 // suspend this thread
|
277 david.dillard 1.50 void suspend();
|
278 mike 1.2
279 // resume this thread
|
280 david.dillard 1.50 void resume();
|
281 mike 1.2 #endif
282
|
283 david.dillard 1.50 static void sleep(Uint32 msec);
|
284 mike 1.2
285 // block the calling thread until this thread terminates
|
286 david.dillard 1.50 void join();
287 void thread_init();
|
288 mike 1.2
289 // thread routine needs to call this function when
290 // it is ready to exit
|
291 david.dillard 1.50 void exit_self(PEGASUS_THREAD_RETURN return_code);
|
292 mike 1.2
293 // stack of functions to be called when thread terminates
294 // will be called last in first out (LIFO)
|
295 david.dillard 1.50 // @exception IPCException
296 void cleanup_push(void (*routine) (void *), void *parm);
297
298 // @exception IPCException
299 void cleanup_pop(Boolean execute = true);
|
300 mike 1.2
301 // create and initialize a tsd
|
302 david.dillard 1.50 // @exception IPCException
303 inline void create_tsd(const char *key, int size, void *buffer)
|
304 mike 1.2 {
|
305 a.arora 1.37 AutoPtr<thread_data> tsd(new thread_data(key, size, buffer));
|
306 a.arora 1.38 _tsd.insert_first(tsd.get());
|
307 a.arora 1.37 tsd.release();
|
308 mike 1.2 }
309
310 // get the buffer associated with the key
|
311 kumpf 1.48 // NOTE: this call leaves the tsd LOCKED !!!!
|
312 david.dillard 1.50 // @exception IPCException
313 inline void *reference_tsd(const char *key)
|
314 mike 1.2 {
|
315 kumpf 1.48 _tsd.lock();
316 thread_data *tsd = _tsd.reference(key);
317 if(tsd != NULL)
318 return( (void *)(tsd->_data) );
319 else
320 return(NULL);
|
321 mike 1.2 }
322
|
323 david.dillard 1.50 // @exception IPCException
324 inline void *try_reference_tsd(const char *key)
|
325 mike 1.2 {
|
326 kumpf 1.48 _tsd.try_lock();
327 thread_data *tsd = _tsd.reference(key);
328 if(tsd != NULL)
329 return((void *)(tsd->_data) );
330 else
331 return(NULL);
|
332 mike 1.2 }
|
333 kumpf 1.48
|
334 mike 1.2
335 // release the lock held on the tsd
336 // NOTE: assumes a corresponding and prior call to reference_tsd() !!!
|
337 david.dillard 1.50 // @exception IPCException
338 inline void dereference_tsd()
|
339 mike 1.2 {
|
340 kumpf 1.48 _tsd.unlock();
|
341 mike 1.2 }
342
343 // delete the tsd associated with the key
|
344 david.dillard 1.50 // @exception IPCException
345 inline void delete_tsd(const char *key)
|
346 mike 1.2 {
|
347 david.dillard 1.43 AutoPtr<thread_data> tsd(_tsd.remove(key));
|
348 mike 1.2 }
349
|
350 kumpf 1.14 // Note: Caller must delete the thread_data object returned (if not null)
|
351 david.dillard 1.50 // @exception IPCException
352 inline void *remove_tsd(const char *key)
|
353 mike 1.2 {
|
354 kumpf 1.48 return(_tsd.remove((const void *)key));
|
355 mike 1.2 }
|
356 kumpf 1.48
|
357 david.dillard 1.50 // @exception IPCException
358 inline void empty_tsd()
|
359 mike 1.2 {
|
360 kumpf 1.48 try
361 {
362 _tsd.try_lock();
363 }
364 catch(IPCException&)
365 {
366 return;
367 }
368
369 AutoPtr<thread_data> tsd(_tsd.next(0));
370 while(tsd.get())
371 {
372 _tsd.remove_no_lock(tsd.get());
373 tsd.reset(_tsd.next(0));
374 }
375 _tsd.unlock();
|
376 mike 1.2 }
|
377 kumpf 1.48
|
378 mike 1.2 // create or re-initialize tsd associated with the key
|
379 kumpf 1.14 // if the tsd already exists, delete the existing buffer
|
380 david.dillard 1.50 // @exception IPCException
|
381 kumpf 1.48 void put_tsd(const char *key, void (*delete_func)(void *), Uint32 size, void *value)
|
382 mike 1.2 {
|
383 kumpf 1.48 PEGASUS_ASSERT(key != NULL);
|
384 david.dillard 1.50 AutoPtr<thread_data> tsd;
|
385 kumpf 1.48 tsd.reset(_tsd.remove((const void *)key)); // may throw an IPC exception
386 tsd.reset();
387 AutoPtr<thread_data> ntsd(new thread_data(key));
388 ntsd->put_data(delete_func, size, value);
389 try { _tsd.insert_first(ntsd.get()); }
390 catch(IPCException& e) { e = e; throw; }
|
391 david.dillard 1.50 ntsd.release();
|
392 mike 1.2 }
|
393 david.dillard 1.50 inline PEGASUS_THREAD_RETURN get_exit() { return _exit_code; }
394 inline PEGASUS_THREAD_TYPE self() {return pegasus_thread_self(); }
|
395 mike 1.2
396 PEGASUS_THREAD_HANDLE getThreadHandle() {return _handle;}
397
|
398 kumpf 1.48 inline Boolean operator==(const void *key) const
399 {
400 if ( (void *)this == key)
401 return(true);
402 return(false);
403 }
|
404 mike 1.2 inline Boolean operator==(const Thread & b) const
405 {
|
406 kumpf 1.48 return(operator==((const void *)&b ));
|
407 mike 1.2 }
408
|
409 david.dillard 1.50 void detach();
|
410 kumpf 1.48
|
411 chuck 1.29 //
412 // Gets the Thread object associated with the caller's thread.
|
413 chuck 1.31 // Note: this may return NULL if no Thread object is associated
414 // with the caller's thread.
|
415 chuck 1.29 //
|
416 chuck 1.28 static Thread * getCurrent(); // l10n
|
417 chuck 1.29
418 //
|
419 chuck 1.31 // Sets the Thread object associated with the caller's thread.
420 // Note: the Thread object must be placed on the heap.
|
421 chuck 1.29 //
|
422 kumpf 1.48 static void setCurrent(Thread * thrd); // l10n
|
423 chuck 1.29
424 //
|
425 a.dunfey 1.53.12.1 // Gets the AcceptLanguageList object associated with the caller's
|
426 chuck 1.29 // Thread.
|
427 chuck 1.31 // Note: this may return NULL if no Thread object, or no
|
428 a.dunfey 1.53.12.1 // AcceptLanguageList object, is associated with the caller's thread.
|
429 kumpf 1.48 //
|
430 a.dunfey 1.53.12.1 static AcceptLanguageList * getLanguages(); //l10n
|
431 kumpf 1.48
|
432 chuck 1.29 //
|
433 a.dunfey 1.53.12.1 // Sets the AcceptLanguageList object associated with the caller's
|
434 chuck 1.29 // Thread.
|
435 chuck 1.31 // Note: a Thread object must have been previously associated with
|
436 kumpf 1.48 // the caller's thread.
|
437 a.dunfey 1.53.12.1 // Note: the AcceptLanguageList object must be placed on the heap.
|
438 kumpf 1.48 //
|
439 a.dunfey 1.53.12.1 static void setLanguages(AcceptLanguageList *langs); //l10n
|
440 kumpf 1.48
|
441 chuck 1.29 //
|
442 a.dunfey 1.53.12.1 // Removes the AcceptLanguageList object associated with the caller's
|
443 chuck 1.29 // Thread.
|
444 kumpf 1.48 //
445 static void clearLanguages(); //l10n
446
|
447 mike 1.2 private:
448 Thread();
|
449 chuck 1.29
450 static Sint8 initializeKey(); // l10n
451
|
452 david.dillard 1.50 // @exception IPCException
453 inline void create_tsd(const char *key )
|
454 mike 1.2 {
|
455 kumpf 1.48 AutoPtr<thread_data> tsd(new thread_data(key));
456 _tsd.insert_first(tsd.get());
457 tsd.release();
|
458 mike 1.2 }
459 PEGASUS_THREAD_HANDLE _handle;
460 Boolean _is_detached;
461 Boolean _cancel_enabled;
|
462 kumpf 1.48 Boolean _cancelled;
463
|
464 mike 1.2 PEGASUS_SEM_HANDLE _suspend_count;
465
466 // always pass this * as the void * parameter to the thread
|
467 kumpf 1.48 // store the user parameter in _thread_parm
|
468 mike 1.2
|
469 david.dillard 1.50 PEGASUS_THREAD_RETURN ( PEGASUS_THREAD_CDECL *_start)(void *);
|
470 mike 1.2 DQueue<class cleanup_handler> _cleanup;
471 DQueue<class thread_data> _tsd;
472
473 void *_thread_parm;
474 PEGASUS_THREAD_RETURN _exit_code;
475 static Boolean _signals_blocked;
|
476 chuck 1.28 static PEGASUS_THREAD_KEY_TYPE _platform_thread_key; //l10n
|
477 kumpf 1.48 static Boolean _key_initialized; // l10n
478 static Boolean _key_error; // l10n
479 };
|
480 mike 1.2
481
482 class PEGASUS_COMMON_LINKAGE ThreadPool
483 {
|
484 kumpf 1.48 public:
|
485 mike 1.2
|
486 kumpf 1.48 /**
487 Constructs a new ThreadPool object.
488 @param initialSize The number of threads that are initially added to
489 the thread pool.
490 @param key A name for this thread pool that can be used to determine
491 equality of two thread pool objects. Only the first 16 characters
492 of this value are used.
493 @param minThreads The minimum number of threads that should be
494 contained in this thread pool at any given time.
495 @param maxThreads The maximum number of threads that should be
496 contained in this thread pool at any given time.
497 @param deallocateWait The minimum time that a thread should be idle
498 before it is removed from the pool and cleaned up.
499 */
500 ThreadPool(
501 Sint16 initialSize,
502 const char* key,
503 Sint16 minThreads,
504 Sint16 maxThreads,
505 struct timeval& deallocateWait);
506
507 kumpf 1.48 /**
508 Destructs the ThreadPool object.
509 */
510 ~ThreadPool();
511
512 /**
513 Allocate and start a thread to do a unit of work.
514 @param parm A generic parameter to pass to the thread
515 @param work A pointer to the function that is to be executed by
516 the thread
517 @param blocking A pointer to an optional semaphore which, if
518 specified, is signaled after the thread finishes
519 executing the work function
|
520 konrad.r 1.53 @return PEGASUS_THREAD_OK if the thread is started successfully,
521 PEGASUS_THREAD_INSUFFICIENT_RESOURCES if the
|
522 kumpf 1.48 resources necessary to start the thread are not currently
|
523 konrad.r 1.53 available. PEGASUS_THREAD_SETUP_FAILURE if the thread
524 could not be setup properly. PEGASUS_THREAD_UNAVAILABLE
525 if this service is shutting down and no more threads can
526 be allocated.
|
527 kumpf 1.48 @exception IPCException
528 */
|
529 konrad.r 1.53 ThreadStatus allocate_and_awaken(
|
530 kumpf 1.48 void* parm,
531 PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL* work)(void *),
532 Semaphore* blocking = 0);
533
534 /**
535 Cleans up idle threads if they have been running longer than the
536 deallocate_wait configuration and more than the configured
537 minimum number of threads is running.
538 @return The number of threads that were cleaned up.
539 @exception IPCException
540 */
541 Uint32 cleanupIdleThreads();
542
543 void get_key(Sint8* buf, int bufsize);
544
545 inline Boolean operator==(const char* key) const
546 {
547 return (!strncmp(key, _key, 16));
548 }
549
|
550 kumpf 1.49 Boolean operator==(const void* p) const
|
551 kumpf 1.48 {
552 return ((void *)this == p);
553 }
554
|
555 kumpf 1.49 Boolean operator==(const ThreadPool & p) const
|
556 kumpf 1.48 {
557 return operator==((const void *)&p);
558 }
559
560 inline void setMinThreads(Sint16 min)
561 {
562 _minThreads = min;
563 }
564
565 inline Sint16 getMinThreads() const
566 {
567 return _minThreads;
568 }
569
570 inline void setMaxThreads(Sint16 max)
571 {
572 _maxThreads = max;
573 }
574
575 inline Sint16 getMaxThreads() const
576 {
577 kumpf 1.48 return _maxThreads;
578 }
579
580 inline Uint32 runningCount()
581 {
582 return _runningThreads.count();
583 }
584
585 inline Uint32 idleCount()
586 {
587 return _idleThreads.count();
588 }
589
590 private:
591
592 ThreadPool(); // Unimplemented
593 ThreadPool(const ThreadPool&); // Unimplemented
594 ThreadPool& operator=(const ThreadPool&); // Unimplemented
595
596 static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL _loop(void *);
597
598 kumpf 1.48 static Boolean _timeIntervalExpired(
599 struct timeval* start,
600 struct timeval* interval);
601
602 static void _deleteSemaphore(void* p);
603
604 void _cleanupThread(Thread* thread);
605 Thread* _initializeThread();
606 void _addToIdleThreadsQueue(Thread* th);
607
608 Sint16 _maxThreads;
609 Sint16 _minThreads;
610 AtomicInt _currentThreads;
611 struct timeval _deallocateWait;
612 char _key[17];
613 DQueue<Thread> _idleThreads;
614 DQueue<Thread> _runningThreads;
615 AtomicInt _dying;
616 };
|
617 mike 1.2
618
619 #if defined(PEGASUS_OS_TYPE_WINDOWS)
620 # include "ThreadWindows_inline.h"
|
621 sage 1.6 #elif defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
622 # include "ThreadzOS_inline.h"
|
623 mike 1.2 #elif defined(PEGASUS_OS_TYPE_UNIX)
624 # include "ThreadUnix_inline.h"
|
625 gs.keenan 1.45 #elif defined(PEGASUS_OS_VMS)
626 # include "ThreadVms_inline.h"
|
627 mike 1.2 #endif
628
629 PEGASUS_NAMESPACE_END
630
631 #endif // Pegasus_Thread_h
|