[
https://issues.apache.org/jira/browse/AMQCPP-564?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14325947#comment-14325947
]
Dusan Kutnik edited comment on AMQCPP-564 at 2/18/15 2:46 PM:
--------------------------------------------------------------
I implemented following methods in the Threading namespace:
////////////////////////////////////////////////////////////////////////////////
void Threading::releaseCurrentThreadHandle() {
ThreadHandle* self =
(ThreadHandle*)PlatformThread::getTlsValue(library->selfKey);
if (self != NULL) {
detachFromCurrentThread(self);
}
}
////////////////////////////////////////////////////////////////////////////////
void Threading::detachFromCurrentThread(ThreadHandle* self) {
PlatformThread::lockMutex(library->globalLock);
// Destroy given Foreign Thread Facade that was created during runtime.
std::vector<Thread*>::iterator iter = library->osThreads.begin();
bool isFound = false;
for (; iter != library->osThreads.end(); ++iter) {
if (self->parent == *iter) {
isFound = true;
break;
}
}
if (isFound) {
PlatformThread::setTlsValue(library->threadKey, NULL);
PlatformThread::setTlsValue(library->selfKey, NULL);
// Ensure all of this thread's local values are purged.
threadExitTlsCleanup(self);
// Destroy OS thread including self thread handle.
delete *iter;
// Remove thread form the global list.
library->osThreads.erase(iter);
}
PlatformThread::unlockMutex(library->globalLock);
}
Both methods are static, the method void
Threading::releaseCurrentThreadHandle() is public and I am using it in the
destructor of my thread object. It seems that the code runs correctly at least
on Windows. I will continue testing it on Linux and Solaris. I encountered no
memory leaks, but it would be nice, if someone could check the correctness of
the implementation. If it's correct, could you add these or similar methods to
a future release of the library?
was (Author: duku):
I implemented following methods in the Threading namespace:
////////////////////////////////////////////////////////////////////////////////
void Threading::releaseCurrentThreadHandle() {
ThreadHandle* self =
(ThreadHandle*)PlatformThread::getTlsValue(library->selfKey);
if (self != NULL) {
detachFromCurrentThread(self);
}
}
////////////////////////////////////////////////////////////////////////////////
void Threading::detachFromCurrentThread(ThreadHandle* self) {
PlatformThread::lockMutex(library->globalLock);
// Destroy given Foreign Thread Facade that was created during runtime.
std::vector<Thread*>::iterator iter = library->osThreads.begin();
bool isFound = false;
for (; iter != library->osThreads.end(); ++iter) {
if (self->parent == *iter) {
isFound = true;
break;
}
}
if (isFound) {
PlatformThread::setTlsValue(library->threadKey, NULL);
PlatformThread::setTlsValue(library->selfKey, NULL);
// Ensure all of this thread's local values are purged.
threadExitTlsCleanup(self);
// Remove thread form the global list.
library->osThreads.erase(iter);
// Destroy OS thread including self thread handle.
delete self->parent;
}
PlatformThread::unlockMutex(library->globalLock);
}
Both methods are static, the method void
Threading::releaseCurrentThreadHandle() is public and I am using it in the
destructor of my thread object. It seems that the code runs correctly at least
on Windows. I will continue testing it on Linux and Solaris. I encountered no
memory leaks, but it would be nice, if someone could check the correctness of
the implementation. If it's correct, could you add these or similar methods to
a future release of the library?
> OS thread handles are kept forever
> ----------------------------------
>
> Key: AMQCPP-564
> URL: https://issues.apache.org/jira/browse/AMQCPP-564
> Project: ActiveMQ C++ Client
> Issue Type: Improvement
> Components: Decaf
> Affects Versions: 3.8.3
> Environment: All
> Reporter: Dusan Kutnik
> Assignee: Timothy Bish
>
> The method
> decaf::internal::util::concurrent::Threading::attachToCurrentThread() creates
> a proxy thread object for a new OS thread and keeps it in a vector:
> ////////////////////////////////////////////////////////////////////////////////
> ThreadHandle* Threading::attachToCurrentThread() {
> Pointer<ThreadHandle> thread(initThreadHandle(new ThreadHandle()));
> thread->handle = PlatformThread::getCurrentThread();
> thread->state = Thread::RUNNABLE;
> thread->stackSize = PlatformThread::getStackSize(thread->handle);
> thread->name = ::strdup(
> std::string(std::string("OS-Thread") +
> Integer::toString(library->osThreadId.getAndIncrement())).c_str());
> thread->threadId = PlatformThread::getCurrentThreadId();
> // An OS Thread doesn't have a running thread, this is only a proxy to
> only one ref.
> thread->references = 1;
> // Now create a Decaf Thread as a proxy to the OS thread.
> Pointer<Thread> osThread(new Thread(thread.get()));
> thread->parent = osThread.get();
> thread->osThread = true;
> PlatformThread::setTlsValue(library->threadKey, osThread.get());
> PlatformThread::setTlsValue(library->selfKey, thread.get());
> // Store the Thread that wraps this OS thread for later deletion since
> // no other owners exist.
> PlatformThread::lockMutex(library->globalLock);
> library->osThreads.push_back(osThread.release());
> PlatformThread::unlockMutex(library->globalLock);
> return thread.release();
> }
> This method is part of the mutex machinery in the AMQ CPP. The only way how
> to free this memory is to invoke the method
> decaf::internal::util::concurrent::Threading::shutdown(). In our scenario we
> create continuously new worker threads that communicate with ActiveMQ broker.
> This leads to the situation that new OS thread handles are still being
> created and never freed. The consumed RAM is rapidly growing since the size
> of the thread object is on our platform (Win 64bit) 1632 Bytes. We would need
> to have possibility to explicitly free this OS thread object before it
> terminates, for instance something like:
> void decaf::internal::util::concurrent::Threading::detachFromCurrentThread()
> Is there a reasonable workaround or another way how to free this OS thread?
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)