[ 
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)

Reply via email to