Update of /cvsroot/boost/boost/libs/thread/src/pthread
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv4876
Added Files:
Tag: thread_rewrite
once.cpp recursive_mutex.cpp tss.cpp
Log Message:
More sources added
--- NEW FILE: once.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/pthread/config.hpp>
#include <boost/thread/pthread/once.hpp>
namespace {
pthread_key_t key;
pthread_once_t once = PTHREAD_ONCE_INIT;
typedef void (*once_callback)();
}
extern "C" {
static void key_init()
{
pthread_key_create(&key, 0);
}
static void do_once()
{
once_callback* cb = reinterpret_cast<once_callback*>(
pthread_getspecific(key));
(**cb)();
}
}
namespace boost {
void call_once(void (*func)(), once_flag& flag)
{
pthread_once(&once, &key_init);
pthread_setspecific(key, &func);
pthread_once(&flag, do_once);
}
}
--- NEW FILE: recursive_mutex.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/pthread/config.hpp>
#include <boost/thread/pthread/recursive_mutex.hpp>
#include <boost/thread/pthread/xtime.hpp>
#include <boost/thread/pthread/thread.hpp>
#include <boost/limits.hpp>
#include <string>
#include <stdexcept>
#include <cassert>
#include <limits>
#include <errno.h>
namespace boost {
recursive_mutex::recursive_mutex()
: m_count(0)
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
, m_valid_id(false)
#endif
{
pthread_mutexattr_t attr;
int res = pthread_mutexattr_init(&attr);
assert(res == 0);
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
assert(res == 0);
#endif
res = pthread_mutex_init(&m_mutex, &attr);
{
# ifndef NDEBUG
int res =
# endif
pthread_mutexattr_destroy(&attr);
assert(res == 0);
}
if (res != 0)
throw thread_resource_error();
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
res = pthread_cond_init(&m_unlocked, 0);
if (res != 0)
{
pthread_mutex_destroy(&m_mutex);
throw thread_resource_error();
}
#endif
}
recursive_mutex::~recursive_mutex()
{
int res = 0;
res = pthread_mutex_destroy(&m_mutex);
assert(res == 0);
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
res = pthread_cond_destroy(&m_unlocked);
assert(res == 0);
#endif
}
void recursive_mutex::do_lock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
if (++m_count > 1)
{
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
#else
pthread_t tid = pthread_self();
if (m_valid_id && pthread_equal(m_thread_id, tid))
++m_count;
else
{
while (m_valid_id)
{
res = pthread_cond_wait(&m_unlocked, &m_mutex);
assert(res == 0);
}
m_thread_id = tid;
m_valid_id = true;
m_count = 1;
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
#endif
}
void recursive_mutex::do_unlock()
{
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
if (--m_count == 0)
{
int res = 0;
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
#else
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
pthread_t tid = pthread_self();
if (m_valid_id && !pthread_equal(m_thread_id, tid))
{
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
throw lock_error();
}
if (--m_count == 0)
{
assert(m_valid_id);
m_valid_id = false;
res = pthread_cond_signal(&m_unlocked);
assert(res == 0);
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
#endif
}
void recursive_mutex::do_lock(cv_state& state)
{
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
m_count = state.count;
#else
int res = 0;
while (m_valid_id)
{
res = pthread_cond_wait(&m_unlocked, &m_mutex);
assert(res == 0);
}
m_thread_id = pthread_self();
m_valid_id = true;
m_count = state.count;
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
#endif
}
void recursive_mutex::do_unlock(cv_state& state)
{
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
assert(m_valid_id);
m_valid_id = false;
res = pthread_cond_signal(&m_unlocked);
assert(res == 0);
#endif
state.pmutex = &m_mutex;
state.count = m_count;
m_count = 0;
}
recursive_try_mutex::recursive_try_mutex()
: m_count(0)
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
, m_valid_id(false)
#endif
{
pthread_mutexattr_t attr;
int res = pthread_mutexattr_init(&attr);
assert(res == 0);
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
res = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
assert(res == 0);
#endif
res = pthread_mutex_init(&m_mutex, &attr);
{
# ifndef NDEBUG
int res =
# endif
pthread_mutexattr_destroy(&attr);
assert(res == 0);
}
if (res != 0)
throw thread_resource_error();
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
res = pthread_cond_init(&m_unlocked, 0);
if (res != 0)
{
pthread_mutex_destroy(&m_mutex);
throw thread_resource_error();
}
#endif
}
recursive_try_mutex::~recursive_try_mutex()
{
int res = 0;
res = pthread_mutex_destroy(&m_mutex);
assert(res == 0);
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
res = pthread_cond_destroy(&m_unlocked);
assert(res == 0);
#endif
}
void recursive_try_mutex::do_lock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
if (++m_count > 1)
{
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
#else
pthread_t tid = pthread_self();
if (m_valid_id && pthread_equal(m_thread_id, tid))
++m_count;
else
{
while (m_valid_id)
{
res = pthread_cond_wait(&m_unlocked, &m_mutex);
assert(res == 0);
}
m_thread_id = tid;
m_valid_id = true;
m_count = 1;
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
#endif
}
bool recursive_try_mutex::do_trylock()
{
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
int res = 0;
res = pthread_mutex_trylock(&m_mutex);
assert(res == 0 || res == EBUSY);
if (res == 0)
{
if (++m_count > 1)
{
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
return true;
}
return false;
#else
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
bool ret = false;
pthread_t tid = pthread_self();
if (m_valid_id && pthread_equal(m_thread_id, tid))
{
++m_count;
ret = true;
}
else if (!m_valid_id)
{
m_thread_id = tid;
m_valid_id = true;
m_count = 1;
ret = true;
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
return ret;
#endif
}
void recursive_try_mutex::do_unlock()
{
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
if (--m_count == 0)
{
int res = 0;
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
#else
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
pthread_t tid = pthread_self();
if (m_valid_id && !pthread_equal(m_thread_id, tid))
{
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
throw lock_error();
}
if (--m_count == 0)
{
assert(m_valid_id);
m_valid_id = false;
res = pthread_cond_signal(&m_unlocked);
assert(res == 0);
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
#endif
}
void recursive_try_mutex::do_lock(cv_state& state)
{
#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
m_count = state.count;
#else
int res = 0;
while (m_valid_id)
{
res = pthread_cond_wait(&m_unlocked, &m_mutex);
assert(res == 0);
}
m_thread_id = pthread_self();
m_valid_id = true;
m_count = state.count;
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
#endif
}
void recursive_try_mutex::do_unlock(cv_state& state)
{
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
assert(m_valid_id);
m_valid_id = false;
res = pthread_cond_signal(&m_unlocked);
assert(res == 0);
#endif
state.pmutex = &m_mutex;
state.count = m_count;
m_count = 0;
}
recursive_timed_mutex::recursive_timed_mutex()
: m_valid_id(false), m_count(0)
{
int res = 0;
res = pthread_mutex_init(&m_mutex, 0);
if (res != 0)
throw thread_resource_error();
res = pthread_cond_init(&m_unlocked, 0);
if (res != 0)
{
pthread_mutex_destroy(&m_mutex);
throw thread_resource_error();
}
}
recursive_timed_mutex::~recursive_timed_mutex()
{
int res = 0;
res = pthread_mutex_destroy(&m_mutex);
assert(res == 0);
res = pthread_cond_destroy(&m_unlocked);
assert(res == 0);
}
void recursive_timed_mutex::do_lock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
pthread_t tid = pthread_self();
if (m_valid_id && pthread_equal(m_thread_id, tid))
++m_count;
else
{
while (m_valid_id)
{
res = pthread_cond_wait(&m_unlocked, &m_mutex);
assert(res == 0);
}
m_thread_id = tid;
m_valid_id = true;
m_count = 1;
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
bool recursive_timed_mutex::do_trylock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
bool ret = false;
pthread_t tid = pthread_self();
if (m_valid_id && pthread_equal(m_thread_id, tid))
{
++m_count;
ret = true;
}
else if (!m_valid_id)
{
m_thread_id = tid;
m_valid_id = true;
m_count = 1;
ret = true;
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
return ret;
}
bool recursive_timed_mutex::do_timedlock(const xtime& xt)
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
bool ret = false;
pthread_t tid = pthread_self();
if (m_valid_id && pthread_equal(m_thread_id, tid))
{
++m_count;
ret = true;
}
else
{
boost::xtime t;
// normalize, in case user has specified nsec only
if (xt.nsec > 999999999)
{
t.sec = xt.nsec / 1000000000;
t.nsec = xt.nsec % 1000000000;
}
else
{
t.sec = t.nsec = 0;
}
timespec ts;
if (xt.sec < std::numeric_limits<time_t>::max() - t.sec) // avoid
overflow
{
ts.tv_sec = static_cast<time_t>(xt.sec + t.sec);
ts.tv_nsec = static_cast<long>(t.nsec);
}
else
{
ts.tv_sec = std::numeric_limits<time_t>::max();
ts.tv_nsec = 999999999; // this should not overflow, or tv_nsec is
odd anyways...
}
// to_timespec(xt, ts);
while (m_valid_id)
{
res = pthread_cond_timedwait(&m_unlocked, &m_mutex, &ts);
if (res == ETIMEDOUT)
break;
assert(res == 0);
}
if (!m_valid_id)
{
m_thread_id = tid;
m_valid_id = true;
m_count = 1;
ret = true;
}
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
return ret;
}
void recursive_timed_mutex::do_unlock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
pthread_t tid = pthread_self();
if (m_valid_id && !pthread_equal(m_thread_id, tid))
{
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
throw lock_error();
}
if (--m_count == 0)
{
assert(m_valid_id);
m_valid_id = false;
res = pthread_cond_signal(&m_unlocked);
assert(res == 0);
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
void recursive_timed_mutex::do_lock(cv_state& state)
{
int res = 0;
while (m_valid_id)
{
res = pthread_cond_wait(&m_unlocked, &m_mutex);
assert(res == 0);
}
m_thread_id = pthread_self();
m_valid_id = true;
m_count = state.count;
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
void recursive_timed_mutex::do_unlock(cv_state& state)
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
assert(m_valid_id);
m_valid_id = false;
res = pthread_cond_signal(&m_unlocked);
assert(res == 0);
state.pmutex = &m_mutex;
state.count = m_count;
m_count = 0;
}
} // namespace boost
--- 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/pthread/config.hpp>
#include <boost/thread/pthread/tss.hpp>
#ifndef BOOST_THREAD_NO_TSS_CLEANUP
#include <boost/thread/pthread/once.hpp>
#include <boost/thread/pthread/mutex.hpp>
#include <boost/thread/pthread/exceptions.hpp>
#include <vector>
#include <string>
#include <stdexcept>
#include <cassert>
namespace {
typedef std::vector<void*> tss_slots;
struct tss_data_t
{
boost::mutex mutex;
std::vector<boost::function1<void, void*>*> cleanup_handlers;
pthread_key_t 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);
int res = pthread_key_create(&temp->native_key, &cleanup_slots);
if (res != 0)
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)
{
tss_slots* slots = 0;
slots = static_cast<tss_slots*>(
pthread_getspecific(tss_data->native_key));
if (slots == 0 && alloc)
{
std::auto_ptr<tss_slots> temp(new tss_slots);
if (pthread_setspecific(tss_data->native_key, temp.get()) != 0)
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
-------------------------------------------------------------------------
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