version 1.88, 2006/01/10 19:41:15
|
version 1.90, 2006/07/11 18:39:28
|
|
|
//%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 |
|
|
void Thread::cleanup_push( void (*routine)(void *), void *parm) | void Thread::cleanup_push( void (*routine)(void *), void *parm) |
{ | { |
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_front(cu.get()); |
cu.release(); | cu.release(); |
return; | return; |
} | } |
|
|
AutoPtr<cleanup_handler> cu; | AutoPtr<cleanup_handler> cu; |
try | try |
{ | { |
cu.reset(_cleanup.remove_first()); |
cu.reset(_cleanup.remove_front()); |
} | } |
catch(IPCException&) | catch(IPCException&) |
{ | { |
|
|
void Thread::exit_self(PEGASUS_THREAD_RETURN exit_code) | void Thread::exit_self(PEGASUS_THREAD_RETURN exit_code) |
{ | { |
// execute the cleanup stack and then return | // execute the cleanup stack and then return |
while( _cleanup.count() ) |
while( _cleanup.size() ) |
{ | { |
try | try |
{ | { |
|
|
: _maxThreads(maxThreads), | : _maxThreads(maxThreads), |
_minThreads(minThreads), | _minThreads(minThreads), |
_currentThreads(0), | _currentThreads(0), |
_idleThreads(true), |
_idleThreads(), |
_runningThreads(true), |
_runningThreads(), |
_dying(0) | _dying(0) |
{ | { |
_deallocateWait.tv_sec = deallocateWait.tv_sec; | _deallocateWait.tv_sec = deallocateWait.tv_sec; |
|
|
"Cleaning up %d idle threads. ", _currentThreads.get()); | "Cleaning up %d idle threads. ", _currentThreads.get()); |
while (_currentThreads.get() > 0) | while (_currentThreads.get() > 0) |
{ | { |
Thread* thread = _idleThreads.remove_first(); |
Thread* thread = _idleThreads.remove_front(); |
if (thread != 0) | if (thread != 0) |
{ | { |
_cleanupThread(thread); | _cleanupThread(thread); |
|
|
blocking_sem->signal(); | blocking_sem->signal(); |
} | } |
| |
Boolean removed = pool->_runningThreads.remove((void *)myself); |
pool->_runningThreads.remove(myself); |
PEGASUS_ASSERT(removed); |
pool->_idleThreads.insert_front(myself); |
|
|
pool->_idleThreads.insert_first(myself); |
|
} | } |
catch (...) | catch (...) |
{ | { |
|
|
gettimeofday(&start, NULL); | gettimeofday(&start, NULL); |
Thread* th = 0; | Thread* th = 0; |
| |
th = _idleThreads.remove_first(); |
th = _idleThreads.remove_front(); |
| |
if (th == 0) | if (th == 0) |
{ | { |
|
|
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.size(), _idleThreads.size()); |
return PEGASUS_THREAD_INSUFFICIENT_RESOURCES; | return PEGASUS_THREAD_INSUFFICIENT_RESOURCES; |
} | } |
| |
|
|
th->put_tsd("blocking sem", NULL, sizeof(Semaphore *), blocking); | th->put_tsd("blocking sem", NULL, sizeof(Semaphore *), blocking); |
| |
// put the thread on the running list | // put the thread on the running list |
_runningThreads.insert_first(th); |
_runningThreads.insert_front(th); |
| |
// signal the thread's sleep semaphore to awaken it | // signal the thread's sleep semaphore to awaken it |
Semaphore* sleep_sem = (Semaphore *)th->reference_tsd("sleep sem"); | Semaphore* sleep_sem = (Semaphore *)th->reference_tsd("sleep sem"); |
|
|
| |
Uint32 numThreadsCleanedUp = 0; | Uint32 numThreadsCleanedUp = 0; |
| |
Uint32 numIdleThreads = _idleThreads.count(); |
Uint32 numIdleThreads = _idleThreads.size(); |
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 |
|
|
break; | break; |
} | } |
| |
Thread* thread = _idleThreads.remove_last(); |
Thread* thread = _idleThreads.remove_back(); |
| |
// If there are no more threads in the _idleThreads queue, we're done. | // If there are no more threads in the _idleThreads queue, we're done. |
if (thread == 0) | if (thread == 0) |
|
|
catch (...) | catch (...) |
{ | { |
PEGASUS_ASSERT(false); | PEGASUS_ASSERT(false); |
_idleThreads.insert_last(thread); |
_idleThreads.insert_back(thread); |
break; | break; |
} | } |
| |
|
|
} | } |
else | else |
{ | { |
_idleThreads.insert_first(thread); |
_idleThreads.insert_front(thread); |
} | } |
} | } |
| |
|
|
| |
try | try |
{ | { |
_idleThreads.insert_first(th); |
_idleThreads.insert_front(th); |
} | } |
catch (...) | catch (...) |
{ | { |
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, | Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
"ThreadPool::_addToIdleThreadsQueue: _idleThreads.insert_first " |
"ThreadPool::_addToIdleThreadsQueue: _idleThreads.insert_front " |
"failed."); | "failed."); |
} | } |
} | } |