Update of /cvsroot/boost/boost/libs/thread/src
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv8244/libs/thread/src
Modified Files:
Tag: RC_1_34_0
tss.cpp
Log Message:
Removed the "intentional memory leak" of the TSS implementation.
Index: tss.cpp
===================================================================
RCS file: /cvsroot/boost/boost/libs/thread/src/tss.cpp,v
retrieving revision 1.16.10.3
retrieving revision 1.16.10.4
diff -u -d -r1.16.10.3 -r1.16.10.4
--- tss.cpp 14 Sep 2006 21:51:00 -0000 1.16.10.3
+++ tss.cpp 1 Oct 2006 12:57:18 -0000 1.16.10.4
@@ -1,5 +1,5 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
+// Copyright (C) 2001-2003 William E. Kempf
+// Copyright (C) 2006 Roland Schwarz
//
// Distributed under the Boost Software License, Version 1.0. (See
accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -25,63 +25,98 @@
namespace {
typedef std::vector<void*> tss_slots;
+typedef std::vector<boost::function1<void, void*>*>
tss_data_cleanup_handlers_type;
-struct tss_data_t
-{
- boost::mutex mutex;
- std::vector<boost::function1<void, void*>*> cleanup_handlers;
+boost::once_flag tss_data_once = BOOST_ONCE_INIT;
+boost::mutex* tss_data_mutex = 0;
+tss_data_cleanup_handlers_type* tss_data_cleanup_handlers = 0;
#if defined(BOOST_HAS_WINTHREADS)
- DWORD native_key;
+ DWORD tss_data_native_key;
#elif defined(BOOST_HAS_PTHREADS)
- pthread_key_t native_key;
+ pthread_key_t tss_data_native_key;
#elif defined(BOOST_HAS_MPTASKS)
- TaskStorageIndex native_key;
+ TaskStorageIndex tss_data_native_key;
#endif
-};
+int tss_data_use = 0;
-tss_data_t* tss_data = 0;
-boost::once_flag tss_data_once = BOOST_ONCE_INIT;
+void tss_data_inc_use(boost::mutex::scoped_lock& lk)
+{
+ ++tss_data_use;
+}
+
+void tss_data_dec_use(boost::mutex::scoped_lock& lk)
+{
+ if (0 == --tss_data_use)
+ {
+ tss_data_cleanup_handlers_type::size_type i;
+ for (i = 0; i < tss_data_cleanup_handlers->size(); ++i)
+ {
+ delete (*tss_data_cleanup_handlers)[i];
+ }
+ delete tss_data_cleanup_handlers;
+ tss_data_cleanup_handlers = 0;
+ lk.unlock();
+ delete tss_data_mutex;
+ tss_data_mutex = 0;
+#if defined(BOOST_HAS_WINTHREADS)
+ TlsFree(tss_data_native_key);
+#elif defined(BOOST_HAS_PTHREADS)
+ pthread_key_delete(tss_data_native_key);
+#elif defined(BOOST_HAS_MPTASKS)
+ // Don't know what to put here.
+ // But MPTASKS isn't currently maintained anyways...
+#endif
+ }
+}
extern "C" void cleanup_slots(void* p)
{
tss_slots* slots = static_cast<tss_slots*>(p);
+ boost::mutex::scoped_lock lock(*tss_data_mutex);
for (tss_slots::size_type i = 0; i < slots->size(); ++i)
{
- boost::mutex::scoped_lock lock(tss_data->mutex);
- (*tss_data->cleanup_handlers[i])((*slots)[i]);
+ (*(*tss_data_cleanup_handlers)[i])((*slots)[i]);
(*slots)[i] = 0;
}
+ tss_data_dec_use(lock);
delete slots;
}
void init_tss_data()
{
- std::auto_ptr<tss_data_t> temp(new tss_data_t);
+ std::auto_ptr<tss_data_cleanup_handlers_type>
+ temp(new tss_data_cleanup_handlers_type);
+
+ std::auto_ptr<boost::mutex> temp_mutex(new boost::mutex);
+ if (temp_mutex.get() == 0)
+ throw boost::thread_resource_error();
#if defined(BOOST_HAS_WINTHREADS)
//Force the cleanup implementation library to be linked in
tss_cleanup_implemented();
//Allocate tls slot
- temp->native_key = TlsAlloc();
- if (temp->native_key == 0xFFFFFFFF)
+ tss_data_native_key = TlsAlloc();
+ if (tss_data_native_key == 0xFFFFFFFF)
return;
#elif defined(BOOST_HAS_PTHREADS)
- int res = pthread_key_create(&temp->native_key, &cleanup_slots);
+ int res = pthread_key_create(&tss_data_native_key, &cleanup_slots);
if (res != 0)
return;
#elif defined(BOOST_HAS_MPTASKS)
- OSStatus status = MPAllocateTaskStorageIndex(&temp->native_key);
+ OSStatus status = MPAllocateTaskStorageIndex(&tss_data_native_key);
if (status != noErr)
return;
#endif
- // Intentional memory "leak"
- // This is the only way to ensure the mutex in the global data
- // structure is available when cleanup handlers are run, since the
- // execution order of cleanup handlers is unspecified on any platform
- // with regards to C++ destructor ordering rules.
- tss_data = temp.release();
+ // The life time of cleanup handlers and mutex is beeing
+ // managed by a reference counting technique.
+ // This avoids a memory leak by releasing the global data
+ // after last use only, since the execution order of cleanup
+ // handlers is unspecified on any platform with regards to
+ // C++ destructor ordering rules.
+ tss_data_cleanup_handlers = temp.release();
+ tss_data_mutex = temp_mutex.release();
}
#if defined(BOOST_HAS_WINTHREADS)
@@ -101,13 +136,13 @@
#if defined(BOOST_HAS_WINTHREADS)
slots = static_cast<tss_slots*>(
- TlsGetValue(tss_data->native_key));
+ TlsGetValue(tss_data_native_key));
#elif defined(BOOST_HAS_PTHREADS)
slots = static_cast<tss_slots*>(
- pthread_getspecific(tss_data->native_key));
+ pthread_getspecific(tss_data_native_key));
#elif defined(BOOST_HAS_MPTASKS)
slots = static_cast<tss_slots*>(
- MPGetTaskStorageValue(tss_data->native_key));
+ MPGetTaskStorageValue(tss_data_native_key));
#endif
if (slots == 0 && alloc)
@@ -117,16 +152,19 @@
#if defined(BOOST_HAS_WINTHREADS)
if (at_thread_exit(&tss_thread_exit) == -1)
return 0;
- if (!TlsSetValue(tss_data->native_key, temp.get()))
+ if (!TlsSetValue(tss_data_native_key, temp.get()))
return 0;
#elif defined(BOOST_HAS_PTHREADS)
- if (pthread_setspecific(tss_data->native_key, temp.get()) != 0)
+ if (pthread_setspecific(tss_data_native_key, temp.get()) != 0)
return 0;
#elif defined(BOOST_HAS_MPTASKS)
- if (MPSetTaskStorageValue(tss_data->native_key, temp.get()) != noErr)
+ if (MPSetTaskStorageValue(tss_data_native_key, temp.get()) != noErr)
return 0;
#endif
-
+ {
+ boost::mutex::scoped_lock lock(*tss_data_mutex);
+ tss_data_inc_use(lock);
+ }
slots = temp.release();
}
@@ -141,13 +179,14 @@
void tss::init(boost::function1<void, void*>* pcleanup)
{
boost::call_once(&init_tss_data, tss_data_once);
- if (tss_data == 0)
+ if (tss_data_cleanup_handlers == 0)
throw thread_resource_error();
- boost::mutex::scoped_lock lock(tss_data->mutex);
+ boost::mutex::scoped_lock lock(*tss_data_mutex);
try
{
- tss_data->cleanup_handlers.push_back(pcleanup);
- m_slot = tss_data->cleanup_handlers.size() - 1;
+ tss_data_cleanup_handlers->push_back(pcleanup);
+ m_slot = tss_data_cleanup_handlers->size() - 1;
+ tss_data_inc_use(lock);
}
catch (...)
{
@@ -155,6 +194,12 @@
}
}
+tss::~tss()
+{
+ boost::mutex::scoped_lock lock(*tss_data_mutex);
+ tss_data_dec_use(lock);
+}
+
void* tss::get() const
{
tss_slots* slots = get_slots(false);
@@ -192,8 +237,8 @@
void tss::cleanup(void* value)
{
- boost::mutex::scoped_lock lock(tss_data->mutex);
- (*tss_data->cleanup_handlers[m_slot])(value);
+ boost::mutex::scoped_lock lock(*tss_data_mutex);
+ (*(*tss_data_cleanup_handlers)[m_slot])(value);
}
} // namespace detail
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs