/** * @copyright * ==================================================================== * Copyright (c) 2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== * @endcopyright * * @file JNIThreadData.cpp * @brief Implementation of the class JNIThreadData */ #include "JNIThreadData.h" #include #include #include #include #include #include "JNIUtil.h" apr_threadkey_t *JNIThreadData::g_key; /** * create and initialize a new object */ JNIThreadData::JNIThreadData() { m_env = NULL; m_exceptionThrown = false; m_requestPool = NULL; m_previous = NULL; } /** * destroy an object */ JNIThreadData::~JNIThreadData() { } /** * initialize the thread local storage * @return success or failure */ bool JNIThreadData::initThreadData() { // if already initialized -> nothing to do if(g_key != NULL) { return false; } // request a key for the thread local storage from the global pool and // register a callback function called, when the thread is deleted apr_status_t apr_err = apr_threadkey_private_create ( &g_key, del, JNIUtil::getPool()); if(apr_err) { JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_create"); return false; } return true; } /** * Get the thread local storage for this thread * @return thread local storage */ JNIThreadData * JNIThreadData::getThreadData() { // we should never be called before initThreadData if(g_key == NULL) { return NULL; } // retrieve the thread local storage from apr JNIThreadData *data = NULL; apr_status_t apr_err = apr_threadkey_private_get (reinterpret_cast(&data), g_key); if(apr_err) { JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_get"); return NULL; } // not already allocated if(data == NULL) { // allocate and store to apr data = new JNIThreadData; apr_err = apr_threadkey_private_set (data, g_key); if(apr_err) { JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_set"); return NULL; } } return data; } /** * Allocate a new ThreadData for the current call from java and push it on the * stack */ void JNIThreadData::pushNewThreadData() { JNIThreadData *data = NULL; apr_status_t apr_err = apr_threadkey_private_get (reinterpret_cast(&data), g_key); if(apr_err) { JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_get"); return; } JNIThreadData *newData = new JNIThreadData(); newData->m_previous =data; apr_err = apr_threadkey_private_set (newData, g_key); if(apr_err) { JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_set"); return; } } /** * Pop the current ThreadData from the stack, because the call is completed */ void JNIThreadData::popThreadData() { JNIThreadData *data = NULL; apr_status_t apr_err = apr_threadkey_private_get (reinterpret_cast(&data), g_key); if(apr_err) { JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_get"); return; } if(data == NULL) { return; } JNIThreadData *oldData = data->m_previous; delete data; apr_err = apr_threadkey_private_set (oldData, g_key); if(apr_err) { JNIUtil::handleAPRError(apr_err, "apr_threadkey_private_set"); return; } } /** * callback called by apr, when the thread dies. Deletes the thread local * storage */ void JNIThreadData::del(void *p) { delete reinterpret_cast(p); }