Update of /cvsroot/boost/boost/libs/thread/src/win32
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv4914
Added Files:
Tag: thread_rewrite
tss.cpp tss_dll.cpp tss_hooks.cpp tss_null.cpp tss_pe.cpp
Log Message:
More sources added
--- NEW FILE: tss.cpp ---
// 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)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#include <boost/thread/win32/config.hpp>
#include <boost/thread/win32/tss.hpp>
#ifndef BOOST_THREAD_NO_TSS_CLEANUP
#include <boost/thread/win32/once.hpp>
#include <boost/thread/win32/mutex.hpp>
#include <boost/thread/win32/exceptions.hpp>
#include <vector>
#include <string>
#include <stdexcept>
#include <cassert>
#include <windows.h>
#include <boost/thread/win32/tss_hooks.hpp>
namespace {
typedef std::vector<void*> tss_slots;
struct tss_data_t
{
boost::mutex mutex;
std::vector<boost::function1<void, void*>*> cleanup_handlers;
DWORD native_key;
};
tss_data_t* tss_data = 0;
boost::once_flag tss_data_once = BOOST_ONCE_INIT;
extern "C" void cleanup_slots(void* p)
{
tss_slots* slots = static_cast<tss_slots*>(p);
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]);
(*slots)[i] = 0;
}
delete slots;
}
void init_tss_data()
{
std::auto_ptr<tss_data_t> temp(new tss_data_t);
//Force the cleanup implementation library to be linked in
tss_cleanup_implemented();
//Allocate tls slot
temp->native_key = TlsAlloc();
if (temp->native_key == 0xFFFFFFFF)
return;
// 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();
}
tss_slots* get_slots(bool alloc);
void __cdecl tss_thread_exit()
{
tss_slots* slots = get_slots(false);
if (slots)
cleanup_slots(slots);
}
tss_slots* get_slots(bool alloc)
{
tss_slots* slots = 0;
slots = static_cast<tss_slots*>(
TlsGetValue(tss_data->native_key));
if (slots == 0 && alloc)
{
std::auto_ptr<tss_slots> temp(new tss_slots);
if (at_thread_exit(&tss_thread_exit) == -1)
return 0;
if (!TlsSetValue(tss_data->native_key, temp.get()))
return 0;
slots = temp.release();
}
return slots;
}
} // namespace
namespace boost {
namespace detail {
void tss::init(boost::function1<void, void*>* pcleanup)
{
boost::call_once(&init_tss_data, tss_data_once);
if (tss_data == 0)
throw thread_resource_error();
boost::mutex::scoped_lock lock(tss_data->mutex);
try
{
tss_data->cleanup_handlers.push_back(pcleanup);
m_slot = tss_data->cleanup_handlers.size() - 1;
}
catch (...)
{
throw thread_resource_error();
}
}
void* tss::get() const
{
tss_slots* slots = get_slots(false);
if (!slots)
return 0;
if (m_slot >= slots->size())
return 0;
return (*slots)[m_slot];
}
void tss::set(void* value)
{
tss_slots* slots = get_slots(true);
if (!slots)
throw boost::thread_resource_error();
if (m_slot >= slots->size())
{
try
{
slots->resize(m_slot + 1);
}
catch (...)
{
throw boost::thread_resource_error();
}
}
(*slots)[m_slot] = value;
}
void tss::cleanup(void* value)
{
boost::mutex::scoped_lock lock(tss_data->mutex);
(*tss_data->cleanup_handlers[m_slot])(value);
}
} // namespace detail
} // namespace boost
#endif //BOOST_THREAD_NO_TSS_CLEANUP
--- NEW FILE: tss_dll.cpp ---
// Copyright (C) 2004 Michael Glassford 2004
// Copyright (C) 2006 Roland Schwarz
// Use, modification and distribution are subject to 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)
#include <boost/thread/win32/config.hpp>
#if defined(BOOST_THREAD_BUILD_DLL)
#include <boost/thread/win32/tss_hooks.hpp>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#if defined(__BORLANDC__)
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE /*hInstance*/, DWORD
dwReason, LPVOID /*lpReserved*/)
#else
extern "C" BOOL WINAPI DllMain(HINSTANCE /*hInstance*/, DWORD dwReason,
LPVOID /*lpReserved*/)
#endif
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
{
on_process_enter();
on_thread_enter();
break;
}
case DLL_THREAD_ATTACH:
{
on_thread_enter();
break;
}
case DLL_THREAD_DETACH:
{
on_thread_exit();
break;
}
case DLL_PROCESS_DETACH:
{
on_thread_exit();
on_process_exit();
break;
}
}
return TRUE;
}
extern "C" void tss_cleanup_implemented(void)
{
/*
This function's sole purpose is to cause a link error in cases where
automatic tss cleanup is not implemented by Boost.Threads as a
reminder that user code is responsible for calling the necessary
functions at the appropriate times (and for implementing an a
tss_cleanup_implemented() function to eliminate the linker's
missing symbol error).
If Boost.Threads later implements automatic tss cleanup in cases
where it currently doesn't (which is the plan), the duplicate
symbol error will warn the user that their custom solution is no
longer needed and can be removed.
*/
}
#endif //defined(BOOST_THREAD_BUILD_DLL)
--- NEW FILE: tss_hooks.cpp ---
// Copyright (C) 2004 Michael Glassford
// Copyright (C) 2006 Peter Dimov
// Copyright (C) 2006 Anthony Williams
// Copyright (C) 2006 Roland Schwarz
//
// Use, modification and distribution are subject to 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)
#include <boost/thread/win32/config.hpp>
#include <boost/thread/win32/tss_hooks.hpp>
#include <boost/assert.hpp>
#include <boost/thread/win32/once.hpp>
#include <list>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
namespace
{
typedef std::list<thread_exit_handler> thread_exit_handlers;
const DWORD invalid_tls_key = TLS_OUT_OF_INDEXES;
DWORD tls_key = invalid_tls_key;
boost::once_flag once_init_tls_key = BOOST_ONCE_INIT;
void init_tls_key()
{
tls_key = TlsAlloc();
}
} // unnamed namespace
extern "C" BOOST_THREAD_DECL int at_thread_exit( thread_exit_handler
exit_handler )
{
boost::call_once( init_tls_key, once_init_tls_key );
if( tls_key == invalid_tls_key )
{
return -1;
}
// Get the exit handlers list for the current thread from tls.
thread_exit_handlers* exit_handlers =
static_cast< thread_exit_handlers* >( TlsGetValue( tls_key ) );
if( exit_handlers == 0 )
{
// No exit handlers list was created yet.
try
{
// Attempt to create a new exit handlers list.
exit_handlers = new thread_exit_handlers;
if( exit_handlers == 0 )
{
return -1;
}
// Attempt to store the list pointer in tls.
if( !TlsSetValue( tls_key, exit_handlers ) )
{
delete exit_handlers;
return -1;
}
}
catch( ... )
{
return -1;
}
}
// Like the C runtime library atexit() function,
// functions should be called in the reverse of
// the order they are added, so push them on the
// front of the list.
try
{
exit_handlers->push_front( exit_handler );
}
catch( ... )
{
return -1;
}
// Like the atexit() function, a result of zero
// indicates success.
return 0;
}
extern "C" BOOST_THREAD_DECL void on_process_enter()
{
}
extern "C" BOOST_THREAD_DECL void on_process_exit()
{
if( tls_key != invalid_tls_key )
{
TlsFree(tls_key);
}
}
extern "C" BOOST_THREAD_DECL void on_thread_enter()
{
}
extern "C" BOOST_THREAD_DECL void on_thread_exit()
{
// Initializing tls_key here ensures its proper visibility
boost::call_once( init_tls_key, once_init_tls_key );
// Get the exit handlers list for the current thread from tls.
if( tls_key == invalid_tls_key )
{
return;
}
thread_exit_handlers* exit_handlers =
static_cast< thread_exit_handlers* >( TlsGetValue( tls_key ) );
// If a handlers list was found, invoke its handlers.
if( exit_handlers != 0 )
{
// Call each handler and remove it from the list
while( !exit_handlers->empty() )
{
if( thread_exit_handler exit_handler = *exit_handlers->begin() )
{
(*exit_handler)();
}
exit_handlers->pop_front();
}
// If TlsSetValue fails, we can't delete the list,
// since a second call to on_thread_exit will try
// to access it.
if( TlsSetValue( tls_key, 0 ) )
{
delete exit_handlers;
}
}
}
--- NEW FILE: tss_null.cpp ---
// Copyright (C) 2004 Michael Glassford 2004
// Copyright (C) 2006 Roland Schwarz
// Use, modification and distribution are subject to 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)
#include <boost/thread/win32/config.hpp>
#if (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST)) &&
!defined(_MSC_VER)
/*
This file is a "null" implementation of tss cleanup; it's
purpose is to to eliminate link errors in cases
where it is known that tss cleanup is not needed.
*/
extern "C" void tss_cleanup_implemented(void)
{
/*
This function's sole purpose is to cause a link error in cases where
automatic tss cleanup is not implemented by Boost.Threads as a
reminder that user code is responsible for calling the necessary
functions at the appropriate times (and for implementing an a
tss_cleanup_implemented() function to eliminate the linker's
missing symbol error).
If Boost.Threads later implements automatic tss cleanup in cases
where it currently doesn't (which is the plan), the duplicate
symbol error will warn the user that their custom solution is no
longer needed and can be removed.
*/
}
#endif //defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER)
--- NEW FILE: tss_pe.cpp ---
// Copyright (C) 2004-2006 Roland Schwarz
// Copyright (C) 2004 Aaron W. LaFramboise
// Copyright (C) 2004 Michael Glassford
// Use, modification and distribution are subject to 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)
#include <boost/thread/win32/config.hpp>
#if defined(BOOST_THREAD_BUILD_LIB) && defined(_MSC_VER)
#include <boost/thread/win32/tss_hooks.hpp>
#include <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//Definitions required by implementation
#if (_MSC_VER < 1310) // 1310 == VC++ 7.1
typedef void (__cdecl *_PVFV)(void);
#define INIRETSUCCESS
#define PVAPI void
#else
typedef int (__cdecl *_PVFV)(void);
#define INIRETSUCCESS 0
#define PVAPI int
#endif
typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
//Symbols for connection to the runtime environment
extern "C"
{
extern DWORD _tls_used; //the tls directory (located in .rdata segment)
extern _TLSCB __xl_a[], __xl_z[]; //tls initializers */
}
namespace
{
//Forward declarations
static PVAPI on_tls_prepare(void);
static PVAPI on_process_init(void);
static PVAPI on_process_term(void);
static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID);
//The .CRT$Xxx information is taken from Codeguru:
//http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
#if (_MSC_VER >= 1310) // 1310 == VC++ 7.1
# pragma data_seg(push, old_seg)
#endif
//Callback to run tls glue code first.
//I don't think it is necessary to run it
//at .CRT$XIB level, since we are only
//interested in thread detachement. But
//this could be changed easily if required.
#pragma data_seg(".CRT$XIU")
static _PVFV p_tls_prepare = on_tls_prepare;
#pragma data_seg()
//Callback after all global ctors.
#pragma data_seg(".CRT$XCU")
static _PVFV p_process_init = on_process_init;
#pragma data_seg()
//Callback for tls notifications.
#pragma data_seg(".CRT$XLB")
_TLSCB p_thread_callback = on_tls_callback;
#pragma data_seg()
//Callback for termination.
#pragma data_seg(".CRT$XTU")
static _PVFV p_process_term = on_process_term;
#pragma data_seg()
#if (_MSC_VER >= 1310) // 1310 == VC++ 7.1
# pragma data_seg(pop, old_seg)
#endif
PVAPI on_tls_prepare(void)
{
//The following line has an important side effect:
//if the TLS directory is not already there, it will
//be created by the linker. In other words, it forces a tls
//directory to be generated by the linker even when static tls
//(i.e. __declspec(thread)) is not used.
//The volatile should prevent the optimizer
//from removing the reference.
DWORD volatile dw = _tls_used;
#if (_MSC_VER < 1310) // 1310 == VC++ 7.1
_TLSCB* pfbegin = __xl_a;
_TLSCB* pfend = __xl_z;
_TLSCB* pfdst = pfbegin;
//pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks;
//The following loop will merge the address pointers
//into a contiguous area, since the tlssup code seems
//to require this (at least on MSVC 6)
while (pfbegin < pfend)
{
if (*pfbegin != 0)
{
*pfdst = *pfbegin;
++pfdst;
}
++pfbegin;
}
*pfdst = 0;
#endif
return INIRETSUCCESS;
}
PVAPI on_process_init(void)
{
//Schedule on_thread_exit() to be called for the main
//thread before destructors of global objects have been
//called.
//It will not be run when 'quick' exiting the
//library; however, this is the standard behaviour
//for destructors of global objects, so that
//shouldn't be a problem.
atexit(on_thread_exit);
//Call Boost process entry callback here
on_process_enter();
return INIRETSUCCESS;
}
PVAPI on_process_term(void)
{
on_process_exit();
return INIRETSUCCESS;
}
void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv)
{
switch (dwReason)
{
case DLL_THREAD_DETACH:
{
on_thread_exit();
break;
}
}
}
} //namespace
extern "C" void tss_cleanup_implemented(void)
{
/*
This function's sole purpose is to cause a link error in cases where
automatic tss cleanup is not implemented by Boost.Threads as a
reminder that user code is responsible for calling the necessary
functions at the appropriate times (and for implementing an a
tss_cleanup_implemented() function to eliminate the linker's
missing symbol error).
If Boost.Threads later implements automatic tss cleanup in cases
where it currently doesn't (which is the plan), the duplicate
symbol error will warn the user that their custom solution is no
longer needed and can be removed.
*/
}
#endif //defined(BOOST_THREAD_BUILD_LIB)
-------------------------------------------------------------------------
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