version 1.82, 2005/05/06 21:44:28
|
version 1.89, 2006/01/30 16:17:08
|
|
|
//%2005//////////////////////////////////////////////////////////////////////// |
//%2006//////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development | // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. | // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
|
|
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. | // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; | // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
// EMC Corporation; VERITAS Software Corporation; The Open Group. | // EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; Symantec Corporation; The Open Group. |
// | // |
// Permission is hereby granted, free of charge, to any person obtaining a copy | // Permission is hereby granted, free of charge, to any person obtaining a copy |
// of this software and associated documentation files (the "Software"), to | // of this software and associated documentation files (the "Software"), to |
|
|
// Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) | // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
// Amit K Arora, IBM (amita@in.ibm.com) for PEP#101 | // Amit K Arora, IBM (amita@in.ibm.com) for PEP#101 |
// Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com) | // Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com) |
|
// David Dillard, VERITAS Software Corp. |
|
// (david.dillard@veritas.com) |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
|
|
{ | { |
if( data != NULL) | if( data != NULL) |
{ | { |
AutoPtr<AcceptLanguages> al(static_cast<AcceptLanguages *>(data)); |
AutoPtr<AcceptLanguageList> al(static_cast<AcceptLanguageList *>(data)); |
} | } |
} | } |
// l10n end | // l10n end |
|
|
Boolean Thread::_key_error = false; | Boolean Thread::_key_error = false; |
| |
| |
// for non-native implementations |
void Thread::cleanup_push( void (*routine)(void *), void *parm) |
#ifndef PEGASUS_THREAD_CLEANUP_NATIVE |
|
void Thread::cleanup_push( void (*routine)(void *), void *parm) throw(IPCException) |
|
{ | { |
AutoPtr<cleanup_handler> cu(new cleanup_handler(routine, parm)); | AutoPtr<cleanup_handler> cu(new cleanup_handler(routine, parm)); |
_cleanup.insert_first(cu.get()); | _cleanup.insert_first(cu.get()); |
|
|
return; | return; |
} | } |
| |
void Thread::cleanup_pop(Boolean execute) throw(IPCException) |
void Thread::cleanup_pop(Boolean execute) |
{ | { |
AutoPtr<cleanup_handler> cu ; | AutoPtr<cleanup_handler> cu ; |
try | try |
|
|
cu->execute(); | cu->execute(); |
} | } |
| |
#endif |
|
|
|
| |
//thread_data *Thread::put_tsd(const Sint8 *key, void (*delete_func)(void *), Uint32 size, void *value) throw(IPCException) |
//thread_data *Thread::put_tsd(const Sint8 *key, void (*delete_func)(void *), Uint32 size, void *value) |
| |
| |
#ifndef PEGASUS_THREAD_EXIT_NATIVE | #ifndef PEGASUS_THREAD_EXIT_NATIVE |
|
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
} | } |
| |
AcceptLanguages * Thread::getLanguages() |
AcceptLanguageList * Thread::getLanguages() |
{ | { |
PEG_METHOD_ENTER(TRC_THREAD, "Thread::getLanguages"); | PEG_METHOD_ENTER(TRC_THREAD, "Thread::getLanguages"); |
| |
Thread * curThrd = Thread::getCurrent(); | Thread * curThrd = Thread::getCurrent(); |
if (curThrd == NULL) | if (curThrd == NULL) |
return NULL; | return NULL; |
AcceptLanguages * acceptLangs = |
AcceptLanguageList * acceptLangs = |
(AcceptLanguages *)curThrd->reference_tsd("acceptLanguages"); |
(AcceptLanguageList *)curThrd->reference_tsd("acceptLanguages"); |
curThrd->dereference_tsd(); | curThrd->dereference_tsd(); |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return acceptLangs; | return acceptLangs; |
} | } |
| |
void Thread::setLanguages(AcceptLanguages *langs) //l10n |
void Thread::setLanguages(AcceptLanguageList *langs) //l10n |
{ | { |
PEG_METHOD_ENTER(TRC_THREAD, "Thread::setLanguages"); | PEG_METHOD_ENTER(TRC_THREAD, "Thread::setLanguages"); |
| |
|
|
// deletes the old tsd and creates a new one | // deletes the old tsd and creates a new one |
currentThrd->put_tsd("acceptLanguages", | currentThrd->put_tsd("acceptLanguages", |
language_delete, | language_delete, |
sizeof(AcceptLanguages *), |
sizeof(AcceptLanguageList *), |
langs); | langs); |
} | } |
| |
|
|
ThreadPool::~ThreadPool() | ThreadPool::~ThreadPool() |
{ | { |
PEG_METHOD_ENTER(TRC_THREAD, "ThreadPool::~ThreadPool"); | PEG_METHOD_ENTER(TRC_THREAD, "ThreadPool::~ThreadPool"); |
|
|
try | try |
{ | { |
// Set the dying flag so all thread know the destructor has been entered | // Set the dying flag so all thread know the destructor has been entered |
_dying++; | _dying++; |
|
Tracer::trace(TRC_THREAD, Tracer::LEVEL2, |
while (_currentThreads.value() > 0) |
"Cleaning up %d idle threads. ", _currentThreads.get()); |
|
while (_currentThreads.get() > 0) |
{ | { |
Thread* thread = _idleThreads.remove_first(); | Thread* thread = _idleThreads.remove_first(); |
if (thread != 0) | if (thread != 0) |
|
|
| |
if (work == 0) | if (work == 0) |
{ | { |
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
Tracer::trace(TRC_THREAD, Tracer::LEVEL4, |
"ThreadPool::_loop: work func is 0, meaning we should exit."); | "ThreadPool::_loop: work func is 0, meaning we should exit."); |
break; | break; |
} | } |
|
|
e.getMessage()); | e.getMessage()); |
} | } |
#if !defined(PEGASUS_OS_LSB) | #if !defined(PEGASUS_OS_LSB) |
catch (exception& e) |
catch (const exception& e) |
{ | { |
PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2, | PEG_TRACE_STRING(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
String("Exception from work in ThreadPool::_loop: ") + | String("Exception from work in ThreadPool::_loop: ") + |
|
|
return((PEGASUS_THREAD_RETURN)0); | return((PEGASUS_THREAD_RETURN)0); |
} | } |
| |
Boolean ThreadPool::allocate_and_awaken( |
ThreadStatus ThreadPool::allocate_and_awaken( |
void* parm, | void* parm, |
PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL* work)(void *), | PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL* work)(void *), |
Semaphore* blocking) | Semaphore* blocking) |
|
|
| |
try | try |
{ | { |
if (_dying.value()) |
if (_dying.get()) |
{ | { |
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, | Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
"ThreadPool::allocate_and_awaken: ThreadPool is dying(1)."); | "ThreadPool::allocate_and_awaken: ThreadPool is dying(1)."); |
// ATTN: Error result has not yet been defined |
return PEGASUS_THREAD_UNAVAILABLE; |
return true; |
|
} | } |
struct timeval start; | struct timeval start; |
gettimeofday(&start, NULL); | gettimeofday(&start, NULL); |
|
|
| |
if (th == 0) | if (th == 0) |
{ | { |
if ((_maxThreads == 0) || (_currentThreads < _maxThreads)) |
if ((_maxThreads == 0) || |
|
(_currentThreads.get() < Uint32(_maxThreads))) |
{ | { |
th = _initializeThread(); | th = _initializeThread(); |
} | } |
|
|
// necessarily imply that a failure has occurred. However, | // necessarily imply that a failure has occurred. However, |
// this label is being used temporarily to help isolate | // this label is being used temporarily to help isolate |
// the cause of client timeout problems. | // the cause of client timeout problems. |
|
|
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, | Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
"ThreadPool::allocate_and_awaken: Insufficient resources: " | "ThreadPool::allocate_and_awaken: Insufficient resources: " |
" pool = %s, running threads = %d, idle threads = %d", | " pool = %s, running threads = %d, idle threads = %d", |
_key, _runningThreads.count(), _idleThreads.count()); | _key, _runningThreads.count(), _idleThreads.count()); |
return false; |
return PEGASUS_THREAD_INSUFFICIENT_RESOURCES; |
} | } |
| |
// initialize the thread data with the work function and parameters | // initialize the thread data with the work function and parameters |
|
|
"ThreadPool::allocate_and_awaken: Operation Failed."); | "ThreadPool::allocate_and_awaken: Operation Failed."); |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
// ATTN: Error result has not yet been defined | // ATTN: Error result has not yet been defined |
return true; |
return PEGASUS_THREAD_SETUP_FAILURE; |
} | } |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return true; |
return PEGASUS_THREAD_OK; |
} | } |
| |
// caller is responsible for only calling this routine during slack periods | // caller is responsible for only calling this routine during slack periods |
|
|
for (Uint32 i = 0; i < numIdleThreads; i++) | for (Uint32 i = 0; i < numIdleThreads; i++) |
{ | { |
// Do not dip below the minimum thread count | // Do not dip below the minimum thread count |
if (_currentThreads.value() <= (Uint32)_minThreads) |
if (_currentThreads.get() <= (Uint32)_minThreads) |
{ | { |
break; | break; |
} | } |
|
|
sizeof(struct timeval), (void *)lastActivityTime); | sizeof(struct timeval), (void *)lastActivityTime); |
// thread will enter _loop() and sleep on sleep_sem until we signal it | // thread will enter _loop() and sleep on sleep_sem until we signal it |
| |
if (!th->run()) |
if (th->run() != PEGASUS_THREAD_OK) |
{ | { |
|
Tracer::trace(TRC_THREAD, Tracer::LEVEL2, |
|
"Could not create thread. Error code is %d.", errno); |
delete th; | delete th; |
return 0; | return 0; |
} | } |