Chris@16: #ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP Chris@16: #define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP Chris@16: Chris@16: // basic_timed_mutex_win32.hpp Chris@16: // Chris@16: // (C) Copyright 2006-8 Anthony Williams Chris@16: // (C) Copyright 2011-2012 Vicente J. Botet Escriba Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #if defined BOOST_THREAD_USES_DATETIME Chris@16: #include Chris@16: #endif Chris@16: #include Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: #include Chris@16: #include Chris@16: #endif Chris@16: #include Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: namespace detail Chris@16: { Chris@16: struct basic_timed_mutex Chris@16: { Chris@16: BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31); Chris@16: BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30); Chris@16: BOOST_STATIC_CONSTANT(long,lock_flag_value=1< Chris@16: bool timed_lock(Duration const& timeout) Chris@16: { Chris@16: return timed_lock(get_system_time()+timeout); Chris@16: } Chris@16: Chris@16: bool timed_lock(boost::xtime const& timeout) Chris@16: { Chris@16: return timed_lock(system_time(timeout)); Chris@16: } Chris@16: #endif Chris@16: #ifdef BOOST_THREAD_USES_CHRONO Chris@16: template Chris@16: bool try_lock_for(const chrono::duration& rel_time) Chris@16: { Chris@16: return try_lock_until(chrono::steady_clock::now() + rel_time); Chris@16: } Chris@16: template Chris@16: bool try_lock_until(const chrono::time_point& t) Chris@16: { Chris@16: using namespace chrono; Chris@16: system_clock::time_point s_now = system_clock::now(); Chris@16: typename Clock::time_point c_now = Clock::now(); Chris@16: return try_lock_until(s_now + ceil(t - c_now)); Chris@16: } Chris@16: template Chris@16: bool try_lock_until(const chrono::time_point& t) Chris@16: { Chris@16: using namespace chrono; Chris@16: typedef time_point sys_tmpt; Chris@16: return try_lock_until(sys_tmpt(chrono::ceil(t.time_since_epoch()))); Chris@16: } Chris@16: bool try_lock_until(const chrono::time_point& tp) Chris@16: { Chris@16: if(try_lock()) Chris@16: { Chris@16: return true; Chris@16: } Chris@16: long old_count=active_count; Chris@16: mark_waiting_and_try_lock(old_count); Chris@16: Chris@16: if(old_count&lock_flag_value) Chris@16: { Chris@16: bool lock_acquired=false; Chris@16: void* const sem=get_event(); Chris@16: Chris@16: do Chris@16: { Chris@101: chrono::time_point now = chrono::system_clock::now(); Chris@101: if (tp<=now) { Chris@101: BOOST_INTERLOCKED_DECREMENT(&active_count); Chris@101: return false; Chris@101: } Chris@101: chrono::milliseconds rel_time= chrono::ceil(tp-now); Chris@16: Chris@101: if(win32::WaitForSingleObjectEx(sem,static_cast(rel_time.count()),0)!=0) Chris@16: { Chris@16: BOOST_INTERLOCKED_DECREMENT(&active_count); Chris@16: return false; Chris@16: } Chris@16: clear_waiting_and_try_lock(old_count); Chris@16: lock_acquired=!(old_count&lock_flag_value); Chris@16: } Chris@16: while(!lock_acquired); Chris@16: } Chris@16: return true; Chris@16: } Chris@16: #endif Chris@16: Chris@16: void unlock() Chris@16: { Chris@16: long const offset=lock_flag_value; Chris@16: long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value); Chris@16: if(!(old_count&event_set_flag_value) && (old_count>offset)) Chris@16: { Chris@16: if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit)) Chris@16: { Chris@16: win32::SetEvent(get_event()); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: void* get_event() Chris@16: { Chris@16: void* current_event=::boost::detail::interlocked_read_acquire(&event); Chris@16: Chris@16: if(!current_event) Chris@16: { Chris@16: void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset); Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable:4311) Chris@16: #pragma warning(disable:4312) Chris@16: #endif Chris@16: void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0); Chris@16: #ifdef BOOST_MSVC Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: if(old_event!=0) Chris@16: { Chris@16: win32::CloseHandle(new_event); Chris@16: return old_event; Chris@16: } Chris@16: else Chris@16: { Chris@16: return new_event; Chris@16: } Chris@16: } Chris@16: return current_event; Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: } Chris@16: } Chris@16: Chris@16: #define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0} Chris@16: Chris@16: #include Chris@16: Chris@16: #endif