⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tss.cpp

📁 C++的一个好库。。。现在很流行
💻 CPP
字号:
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation.  William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.

#include <boost/thread/detail/config.hpp>

#include <boost/thread/tss.hpp>
#ifndef BOOST_THREAD_NO_TSS_CLEANUP

#include <boost/thread/once.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/exceptions.hpp>
#include <vector>
#include <string>
#include <stdexcept>
#include <cassert>

#if defined(BOOST_HAS_WINTHREADS)
#   include <windows.h>
#   include <boost/thread/detail/tss_hooks.hpp>
#endif

namespace {

typedef std::vector<void*> tss_slots;

struct tss_data_t
{
    boost::mutex mutex;
    std::vector<boost::function1<void, void*>*> cleanup_handlers;
#if defined(BOOST_HAS_WINTHREADS)
    DWORD native_key;
#elif defined(BOOST_HAS_PTHREADS)
    pthread_key_t native_key;
#elif defined(BOOST_HAS_MPTASKS)
    TaskStorageIndex native_key;
#endif
};

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;
    }
}

void init_tss_data()
{
    std::auto_ptr<tss_data_t> temp(new tss_data_t);

#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)
        return;
#elif defined(BOOST_HAS_PTHREADS)
    int res = pthread_key_create(&temp->native_key, &cleanup_slots);
    if (res != 0)
        return;
#elif defined(BOOST_HAS_MPTASKS)
    OSStatus status = MPAllocateTaskStorageIndex(&temp->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();
}

#if defined(BOOST_HAS_WINTHREADS)
tss_slots* get_slots(bool alloc);

void __cdecl tss_thread_exit()
{
    tss_slots* slots = get_slots(false);
    if (slots)
        cleanup_slots(slots);
}
#endif

tss_slots* get_slots(bool alloc)
{
    tss_slots* slots = 0;

#if defined(BOOST_HAS_WINTHREADS)
    slots = static_cast<tss_slots*>(
        TlsGetValue(tss_data->native_key));
#elif defined(BOOST_HAS_PTHREADS)
    slots = static_cast<tss_slots*>(
        pthread_getspecific(tss_data->native_key));
#elif defined(BOOST_HAS_MPTASKS)
    slots = static_cast<tss_slots*>(
        MPGetTaskStorageValue(tss_data->native_key));
#endif

    if (slots == 0 && alloc)
    {
        std::auto_ptr<tss_slots> temp(new tss_slots);

#if defined(BOOST_HAS_WINTHREADS)
        if (at_thread_exit(&tss_thread_exit) == -1)
            return 0;
        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)
            return 0;
#elif defined(BOOST_HAS_MPTASKS)
        if (MPSetTaskStorageValue(tss_data->native_key, temp.get()) != noErr)
            return 0;
#endif

        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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -