mirror of
https://github.com/boostorg/thread.git
synced 2026-01-30 20:32:10 +00:00
header-only once for POSIX
[SVN r39695]
This commit is contained in:
@@ -25,7 +25,6 @@ lib boost_thread_pthread
|
||||
pthread/condition.cpp
|
||||
pthread/exceptions.cpp
|
||||
pthread/xtime.cpp
|
||||
pthread/once.cpp
|
||||
pthread/tss.cpp
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_POSIX
|
||||
@@ -41,7 +40,6 @@ lib boost_thread
|
||||
pthread/condition.cpp
|
||||
pthread/exceptions.cpp
|
||||
pthread/xtime.cpp
|
||||
pthread/once.cpp
|
||||
pthread/tss.cpp
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_POSIX
|
||||
|
||||
@@ -1,16 +1,57 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
#ifndef BOOST_THREAD_CONDITION_HPP
|
||||
#define BOOST_THREAD_CONDITION_HPP
|
||||
// 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.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06040706_HPP
|
||||
#define BOOST_THREAD_RS06040706_HPP
|
||||
// (C) Copyright 2007 Anthony Williams
|
||||
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(condition.hpp)
|
||||
#include BOOST_THREAD_PLATFORM(condition_state.hpp)
|
||||
|
||||
#endif // BOOST_THREAD_RS06040706_HPP
|
||||
namespace boost
|
||||
{
|
||||
template <class Mutex>
|
||||
class condition:
|
||||
private boost::detail::thread::condition_state<Mutex>
|
||||
{
|
||||
public:
|
||||
typedef Mutex mutex_type;
|
||||
|
||||
condition();
|
||||
explicit condition(mutex_type& m);
|
||||
~condition();
|
||||
|
||||
#ifdef BOOST_HAS_DELETED_FUNCTIONS
|
||||
condition(const condition&) = delete;
|
||||
condition& operator=(const condition&) = delete;
|
||||
#endif
|
||||
|
||||
void notify_one();
|
||||
void notify_all();
|
||||
|
||||
template <class Lock>
|
||||
void wait(Lock& lock);
|
||||
|
||||
template <class Lock, class Predicate>
|
||||
void wait(Lock& lock, Predicate pred);
|
||||
|
||||
template <class Lock>
|
||||
bool timed_wait(Lock& lock, const utc_time& abs_time);
|
||||
|
||||
template <class Lock, class Predicate>
|
||||
bool timed_wait(Lock& lock, const utc_time& abs_time, Predicate pred);
|
||||
|
||||
#ifndef BOOST_HAS_DELETED_FUNCTIONS
|
||||
private:
|
||||
explicit condition(condition&);
|
||||
condition& operator=(condition&);
|
||||
#endif
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#include BOOST_THREAD_PLATFORM(condition_impl.hpp)
|
||||
#include <boost/thread/utc_time.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,25 +1,74 @@
|
||||
// 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.
|
||||
#ifndef BOOST_THREAD_PTHREAD_ONCE_HPP
|
||||
#define BOOST_THREAD_PTHREAD_ONCE_HPP
|
||||
|
||||
#ifndef BOOST_ONCE_RS06092301_HPP
|
||||
#define BOOST_ONCE_RS06092301_HPP
|
||||
// once.hpp
|
||||
//
|
||||
// (C) Copyright 2007 Anthony Williams
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/pthread/config.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
typedef pthread_once_t once_flag;
|
||||
#define BOOST_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
struct once_flag
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
unsigned flag;
|
||||
};
|
||||
|
||||
void BOOST_THREAD_DECL call_once(void (*func)(), once_flag& flag);
|
||||
#define BOOST_ONCE_INIT {PTHREAD_MUTEX_INITIALIZER,0}
|
||||
|
||||
} // namespace boost
|
||||
namespace detail
|
||||
{
|
||||
struct pthread_mutex_scoped_lock
|
||||
{
|
||||
pthread_mutex_t * mutex;
|
||||
|
||||
explicit pthread_mutex_scoped_lock(pthread_mutex_t* mutex_):
|
||||
mutex(mutex_)
|
||||
{
|
||||
int const res=pthread_mutex_lock(mutex);
|
||||
BOOST_ASSERT(!res);
|
||||
}
|
||||
~pthread_mutex_scoped_lock()
|
||||
{
|
||||
int const res=pthread_mutex_unlock(mutex);
|
||||
BOOST_ASSERT(!res);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BOOST_ONCE_RS06092301_HPP
|
||||
template<typename Function>
|
||||
void call_once(once_flag& flag,Function f)
|
||||
{
|
||||
long const function_complete_flag_value=0xc15730e2;
|
||||
|
||||
#ifdef BOOST_PTHREAD_HAS_ATOMICS
|
||||
if(::boost::detail::interlocked_read_acquire(&flag.flag)!=function_complete_flag_value)
|
||||
{
|
||||
#endif
|
||||
detail::pthread_mutex_scoped_lock const lock(&flag.mutex);
|
||||
if(flag.flag!=function_complete_flag_value)
|
||||
{
|
||||
f();
|
||||
#ifdef BOOST_PTHREAD_HAS_ATOMICS
|
||||
::boost::detail::interlocked_write_release(&flag.flag,function_complete_flag_value);
|
||||
#else
|
||||
flag.flag=function_complete_flag_value;
|
||||
#endif
|
||||
}
|
||||
#ifdef BOOST_PTHREAD_HAS_ATOMICS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
// interlocked_read_win32.hpp
|
||||
//
|
||||
// (C) Copyright 2005-6 Anthony Williams
|
||||
// (C) Copyright 2005-7 Anthony Williams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -15,13 +15,17 @@ namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read(long* x)
|
||||
inline long interlocked_read_acquire(long volatile* x)
|
||||
{
|
||||
return BOOST_INTERLOCKED_EXCHANGE_ADD(x,0);
|
||||
long const res=*x;
|
||||
_ReadWriteBarrier();
|
||||
return res;
|
||||
}
|
||||
inline void* interlocked_read(void** x)
|
||||
inline void* interlocked_read_acquire(void* volatile* x)
|
||||
{
|
||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
|
||||
void* const res=*x;
|
||||
_ReadWriteBarrier();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
// once.hpp
|
||||
//
|
||||
// (C) Copyright 2005-6 Anthony Williams
|
||||
// (C) Copyright 2005-7 Anthony Williams
|
||||
// (C) Copyright 2005 John Maddock
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
@@ -35,29 +35,19 @@ namespace boost
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct handle_closer
|
||||
{
|
||||
void* const handle_to_close;
|
||||
handle_closer(void* handle_to_close_):
|
||||
handle_to_close(handle_to_close_)
|
||||
{}
|
||||
~handle_closer()
|
||||
{
|
||||
win32::CloseHandle(handle_to_close);
|
||||
}
|
||||
};
|
||||
|
||||
struct win32_mutex_scoped_lock
|
||||
{
|
||||
void* const mutex_handle;
|
||||
win32_mutex_scoped_lock(void* mutex_handle_):
|
||||
explicit win32_mutex_scoped_lock(void* mutex_handle_):
|
||||
mutex_handle(mutex_handle_)
|
||||
{
|
||||
win32::WaitForSingleObject(mutex_handle,win32::infinite);
|
||||
unsigned long const res=win32::WaitForSingleObject(mutex_handle,win32::infinite);
|
||||
BOOST_ASSERT(!res);
|
||||
}
|
||||
~win32_mutex_scoped_lock()
|
||||
{
|
||||
win32::ReleaseMutex(mutex_handle);
|
||||
bool const success=win32::ReleaseMutex(mutex_handle)!=0;
|
||||
BOOST_ASSERT(success);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -98,21 +88,21 @@ namespace boost
|
||||
|
||||
|
||||
template<typename Function>
|
||||
void call_once(Function f,once_flag& flag)
|
||||
void call_once(once_flag& flag,Function f)
|
||||
{
|
||||
// Try for a quick win: if the proceedure has already been called
|
||||
// just skip through:
|
||||
long const function_complete_flag_value=0xc15730e2;
|
||||
|
||||
if(::boost::detail::interlocked_read(&flag)!=function_complete_flag_value)
|
||||
if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
|
||||
{
|
||||
char mutex_name[::boost::detail::once_mutex_name_length];
|
||||
void* const mutex_handle(::boost::detail::create_once_mutex(mutex_name,&flag));
|
||||
BOOST_ASSERT(mutex_handle);
|
||||
detail::handle_closer const closer(mutex_handle);
|
||||
detail::win32::handle_manager const closer(mutex_handle);
|
||||
detail::win32_mutex_scoped_lock const lock(mutex_handle);
|
||||
|
||||
if(::boost::detail::interlocked_read(&flag)!=function_complete_flag_value)
|
||||
if(flag!=function_complete_flag_value)
|
||||
{
|
||||
f();
|
||||
BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
# include <windows.h>
|
||||
@@ -110,13 +112,84 @@ namespace boost
|
||||
|
||||
inline handle create_anonymous_event(event_type type,initial_event_state state)
|
||||
{
|
||||
return CreateEventA(0,type,state,0);
|
||||
handle const res=CreateEventA(0,type,state,0);
|
||||
return res?res:throw thread_resource_error();
|
||||
}
|
||||
|
||||
inline handle create_anonymous_semaphore(long initial_count,long max_count)
|
||||
{
|
||||
return CreateSemaphoreA(NULL,initial_count,max_count,NULL);
|
||||
handle const res=CreateSemaphoreA(NULL,initial_count,max_count,NULL);
|
||||
return res?res:throw thread_resource_error();
|
||||
}
|
||||
|
||||
inline handle duplicate_handle(handle source)
|
||||
{
|
||||
handle const current_process=GetCurrentProcess();
|
||||
long const same_access_flag=2;
|
||||
handle new_handle=0;
|
||||
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
return success?new_handle:throw thread_resource_error();
|
||||
}
|
||||
|
||||
inline void release_semaphore(handle semaphore,long count)
|
||||
{
|
||||
bool const success=ReleaseSemaphore(semaphore,count,0);
|
||||
BOOST_ASSERT(success);
|
||||
}
|
||||
|
||||
class handle_manager
|
||||
{
|
||||
private:
|
||||
handle handle_to_manage;
|
||||
handle_manager(handle_manager&);
|
||||
handle_manager& operator=(handle_manager&);
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
if(handle_to_manage)
|
||||
{
|
||||
unsigned long result=CloseHandle(handle_to_manage);
|
||||
BOOST_ASSERT(result);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit handle_manager(handle handle_to_manage_):
|
||||
handle_to_manage(handle_to_manage_)
|
||||
{}
|
||||
handle_manager():
|
||||
handle_to_manage(0)
|
||||
{}
|
||||
|
||||
handle_manager& operator=(handle new_handle)
|
||||
{
|
||||
cleanup();
|
||||
handle_to_manage=new_handle;
|
||||
}
|
||||
|
||||
operator handle() const
|
||||
{
|
||||
return handle_to_manage;
|
||||
}
|
||||
|
||||
handle release()
|
||||
{
|
||||
handle const res=handle_to_manage;
|
||||
handle_to_manage=0;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !handle_to_manage;
|
||||
}
|
||||
|
||||
~handle_manager()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,7 +22,7 @@ struct condition_test_data
|
||||
condition_test_data() : notified(0), awoken(0) { }
|
||||
|
||||
boost::mutex mutex;
|
||||
boost::condition condition;
|
||||
boost::condition<boost::mutex> condition;
|
||||
int notified;
|
||||
int awoken;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
// (C) Copyright 2006-7 Anthony Williams
|
||||
// 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,7 +25,7 @@ void call_once_thread()
|
||||
int my_once_value=0;
|
||||
for(unsigned i=0;i<loop_count;++i)
|
||||
{
|
||||
boost::call_once(initialize_variable, flag);
|
||||
boost::call_once(flag, initialize_variable);
|
||||
my_once_value=var_to_init;
|
||||
if(my_once_value!=1)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user