Implements standard C++ mutex/condition variable requirements for Interprocess utilities.

Fixes #149 ("interprocess_condition_any::timed_wait update")
This commit is contained in:
Ion Gaztañaga
2021-08-19 00:38:24 +02:00
parent 8ec3dfb396
commit 512f95cb07
43 changed files with 1054 additions and 216 deletions

View File

@@ -1383,7 +1383,7 @@ All the mutex types from [*Boost.Interprocess] implement the following operation
[*Throws:] *interprocess_exception* on error.
[blurb ['[*bool timed_lock(const boost::posix_time::ptime &abs_time)]]]
[blurb ['[*template<class TimePoint> bool timed_lock(const TimePoint &abs_time)]]]
[*Effects:] The calling thread will try to obtain exclusive ownership of the mutex if it can do so in until the specified time is reached. If the mutex supports recursive locking, the mutex must be unlocked the same number of times it is locked.
@@ -1399,8 +1399,8 @@ All the mutex types from [*Boost.Interprocess] implement the following operation
[*Throws:] An exception derived from *interprocess_exception* on error.
[important `boost::posix_time::ptime` absolute time points used by Boost.Interprocess synchronization mechanisms
are UTC time points, not local time points]
[important Boost.Interprocess timed synchronization mechanisms support several timepoints: `boost::posix_time::ptime` absolute UTC time points,
`boost::chrono` and `std::chrono` timepoints. Additionally Interprocess' mutexes meet standard C++ `TimedLockable` requirements for std-compatibility]
[endsect]
@@ -1499,8 +1499,8 @@ try_lock, timed_lock a mutex or not to lock it at all.
For more information, check the
[classref boost::interprocess::scoped_lock scoped_lock's reference].
[important `boost::posix_time::ptime` absolute time points used by Boost.Interprocess synchronization mechanisms
are UTC time points, not local time points]
[important Boost.Interprocess timed synchronization operations support several timepoints: `boost::posix_time::ptime` absolute UTC time points,
`boost::chrono` and `std::chrono` timepoints]
[endsect]
@@ -1857,7 +1857,7 @@ If it has to wait, returns false.
[*Throws:] *interprocess_exception* on error.
[blurb ['[*bool timed_lock(const boost::posix_time::ptime &abs_time)]]]
[blurb ['[*template<class TimePoint> bool timed_lock(const TimePoint &abs_time)]]]
[*Effects:]
The calling thread tries to acquire exclusive ownership of the mutex
@@ -1902,7 +1902,7 @@ If it has to wait, returns false.
[*Throws:] *interprocess_exception* on error.
[blurb ['[*bool timed_lock_sharable(const boost::posix_time::ptime &abs_time)]]]
[blurb ['[*template <class TimePoint> bool timed_lock_sharable(const TimePoint &abs_time)]]]
[*Effects:]
The calling thread tries to acquire sharable ownership of the mutex
@@ -1947,7 +1947,7 @@ If it has to wait, returns false.
[*Throws:] *interprocess_exception* on error.
[blurb ['[*bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time)]]]
[blurb ['[*template <class TimePoint> bool timed_lock_upgradable(const TimePoint &abs_time)]]]
[*Effects:]
The calling thread tries to acquire upgradable ownership of the mutex
@@ -2019,7 +2019,9 @@ it will maintain upgradable ownership.
[*Returns:] If acquires exclusive ownership, returns true. Otherwise
returns false.
[*Throws:] An exception derived from *interprocess_exception* on error.[blurb ['[*bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time)]]]
[*Throws:] An exception derived from *interprocess_exception* on error.
[blurb ['[*template <class TimePoint> bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time)]]]
[*Precondition:] The thread must have upgradable ownership of the mutex.
@@ -2042,7 +2044,9 @@ but it will maintain sharable ownership.
[*Returns:] If acquires exclusive ownership, returns true. Otherwise
returns false.
[*Throws:] An exception derived from *interprocess_exception* on error.[blurb ['[*bool try_unlock_sharable_and_lock_upgradable()]]]
[*Throws:] An exception derived from *interprocess_exception* on error.
[blurb ['[*bool try_unlock_sharable_and_lock_upgradable()]]]
[*Precondition:] The thread must have sharable ownership of the mutex.
@@ -2055,8 +2059,8 @@ returns false.
[*Throws:] An exception derived from *interprocess_exception* on error.
[important `boost::posix_time::ptime` absolute time points used by Boost.Interprocess synchronization mechanisms
are UTC time points, not local time points]
[important Boost.Interprocess timed synchronization mechanisms support several timepoints: `boost::posix_time::ptime` absolute UTC time points,
`boost::chrono` and `std::chrono` timepoints.]
[endsect]
@@ -2096,6 +2100,8 @@ Boost.Interprocess offers the following upgradable mutex types:
* [classref boost::interprocess::named_upgradable_mutex named_upgradable_mutex]: A non-recursive,
named upgradable mutex.
[important Interprocess shared mutexes meet standard C++ `SharedTimedMutex` requirements for std-compatibility]
[endsect]
[section:sharable_upgradable_locks Sharable Lock And Upgradable Lock]
@@ -2234,8 +2240,8 @@ upgradable mutex is always unlocked when an exception occurs.
[classref boost::interprocess::sharable_lock sharable_lock] offer
more features and operations, see their reference for more informations
[important `boost::posix_time::ptime` absolute time points used by Boost.Interprocess synchronization mechanisms
are UTC time points, not local time points]
[important Boost.Interprocess timed synchronization mechanisms support several timepoints: `boost::posix_time::ptime` absolute UTC time points,
`boost::chrono` and `std::chrono` timepoints.]
[endsect]
@@ -2392,8 +2398,8 @@ is permitted:
scoped_lock<Mutex> e_lock(move(s_lock, try_to_lock));
}
[important `boost::posix_time::ptime` absolute time points used by Boost.Interprocess synchronization mechanisms
are UTC time points, not local time points]
[important Boost.Interprocess timed synchronization mechanisms support several timepoints: `boost::posix_time::ptime` absolute UTC time points,
`boost::chrono` and `std::chrono` timepoints.]
[endsect]
@@ -2654,7 +2660,7 @@ If it has to wait, returns false.
[*Throws:] *interprocess_exception* on error.
[blurb ['[*bool timed_lock(const boost::posix_time::ptime &abs_time)]]]
[blurb ['[*template <class TimePoint> bool timed_lock(const TimePoint &abs_time)]]]
[*Effects:]
The calling thread tries to acquire exclusive ownership of the file lock
@@ -2695,7 +2701,7 @@ If it has to wait, returns false.
[*Throws:] *interprocess_exception* on error.
[blurb ['[*bool timed_lock_sharable(const boost::posix_time::ptime &abs_time)]]]
[blurb ['[*template <class TimePoint> bool timed_lock_sharable(const TimePoint &abs_time)]]]
[*Effects:]
The calling thread tries to acquire sharable ownership of the file lock
@@ -2718,8 +2724,8 @@ returns false.
For more file locking methods, please
[classref boost::interprocess::file_lock file_lock reference].
[important `boost::posix_time::ptime` absolute time points used by Boost.Interprocess synchronization mechanisms
are UTC time points, not local time points]
[important Boost.Interprocess timed synchronization mechanisms support several timepoints: `boost::posix_time::ptime` absolute UTC time points,
`boost::chrono` and `std::chrono` timepoints.]
[endsect]
@@ -6797,7 +6803,12 @@ thank them:
[section:release_notes_boost_1_78_00 Boost 1.78 Release]
* Mutexes and condition variables now additionally offer a standard C++-like interface to allow reusing code that
is already working with standard thread utilities. E.g.: mutexes meet `TimedLockable` requirements and condition
variables implement `wait_until/wait_for` operations.
* Fixed bugs:
* [@https://github.com/boostorg/interprocess/issues/149 GitHub #149 (['"interprocess_condition_any::timed_wait update"])].
* [@https://github.com/boostorg/interprocess/issues/145 GitHub #145 (['"1.76 now requires unicode paths on windows"])].
[endsect]

View File

@@ -166,6 +166,15 @@ class ustime
ustime operator + (const usduration &other)
{ ustime r(*this); r += other; return r; }
ustime &operator -= (const usduration &other)
{ m_microsecs -= other.m_microsecs; return *this; }
ustime operator - (const usduration &other)
{ ustime r(*this); r -= other; return r; }
friend usduration operator - (const ustime &l, const ustime &r)
{ return usduration(l.m_microsecs - r.m_microsecs); }
bool operator < (const ustime &other) const
{ return m_microsecs < other.m_microsecs; }
@@ -296,6 +305,22 @@ inline bool is_pos_infinity(const TimePoint &, typename disable_if_ptime<TimePoi
return false;
}
/*
template<class Duration>
inline ustime duration_to_timepoint(const Duration &dur, typename enable_if_ptime<Duration>::type* = 0)
{
return dur.is_pos_infinity();
}
template<class Duration>
inline bool duration_to_timepoint(const Duration &, typename disable_if_ptime<Duration>::type* = 0)
{
return false;
}
*/
// duration_to_milliseconds
template<class Duration>
inline boost::uint64_t duration_to_milliseconds(const Duration &abs_time, typename enable_if_ptime_duration<Duration>::type* = 0)
{
@@ -309,6 +334,34 @@ inline boost::uint64_t duration_to_milliseconds(const Duration &d, typename enab
return static_cast<boost::uint64_t>(d.count()*factor);
}
inline boost::uint64_t duration_to_milliseconds(const usduration &d)
{
return d.get_microsecs()/1000;
}
// duration_to_usduration
template<class Duration>
inline usduration duration_to_usduration(const Duration &d, typename enable_if_ptime_duration<Duration>::type* = 0)
{
return usduration(d.total_microseconds());
}
template<class Duration>
inline usduration duration_to_usduration(const Duration &d, typename enable_if_duration<Duration>::type* = 0)
{
const double factor = double(Duration::period::num)*1000000.0/double(Duration::period::den);
return usduration(static_cast<boost::uint64_t>(d.count()*factor));
}
// duration_to_ustime
template<class Duration>
inline ustime duration_to_ustime(const Duration &d)
{
return microsec_clock<ustime>::universal_time() + (duration_to_usduration)(d);
}
} //namespace ipcdetail {
} //namespace interprocess {

View File

@@ -0,0 +1,29 @@
// cv_status.hpp
//
// Copyright (C) 2011 Vicente J. Botet Escriba
// Copyright (C) 2021 Ion Gaztanaga
//
// 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)
#ifndef BOOST_INTERPROCESS_CV_STATUS_HPP
#define BOOST_INTERPROCESS_CV_STATUS_HPP
#include <boost/core/scoped_enum.hpp>
namespace boost {
namespace interprocess {
// enum class cv_status;
BOOST_SCOPED_ENUM_DECLARE_BEGIN(cv_status)
{
no_timeout,
timeout
}
BOOST_SCOPED_ENUM_DECLARE_END(cv_status)
} //namespace interprocess
} //namespace boost
#endif // header

View File

@@ -138,6 +138,16 @@ class file_lock
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
@@ -157,6 +167,11 @@ class file_lock
//! an exception could be thrown.
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! without waiting. If no other thread has exclusive ownership of the
//! mutex this succeeds.
@@ -165,6 +180,11 @@ class file_lock
//!Throws: interprocess_exception on error.
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
//! waiting if necessary until no other thread has exclusive ownership of
//! the mutex or abs_time is reached.
@@ -173,10 +193,26 @@ class file_lock
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
file_handle_t m_file_hnd;

View File

@@ -24,6 +24,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/detail/locks.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -129,6 +130,30 @@ class interprocess_condition
return m_condition.timed_wait(internal_lock, abs_time, pred);
}
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:

View File

@@ -24,6 +24,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -118,6 +119,30 @@ class interprocess_condition_any
template <typename L, class TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{ return m_cond.timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
};
} //namespace interprocess

View File

@@ -139,6 +139,16 @@ class interprocess_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: interprocess_exception on error.
void unlock();

View File

@@ -122,6 +122,16 @@ class interprocess_recursive_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//! If the mutex supports recursive locking, the mutex must be unlocked the
//! same number of times it is locked.

View File

@@ -98,6 +98,16 @@ class interprocess_sharable_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
@@ -117,6 +127,11 @@ class interprocess_sharable_mutex
//! an exception could be thrown.
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
@@ -131,6 +146,11 @@ class interprocess_sharable_mutex
//! an exception could be thrown.
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
@@ -145,11 +165,26 @@ class interprocess_sharable_mutex
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
typedef scoped_lock<interprocess_mutex> scoped_lock_t;

View File

@@ -96,6 +96,17 @@ class interprocess_upgradable_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
@@ -115,6 +126,11 @@ class interprocess_upgradable_mutex
//! an exception could be thrown.
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
@@ -129,6 +145,11 @@ class interprocess_upgradable_mutex
//! an exception could be thrown.
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
@@ -143,11 +164,26 @@ class interprocess_upgradable_mutex
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
//Upgradable locking
//!Requires: The calling thread does not own the mutex.

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/interprocess_tester.hpp>
@@ -147,6 +149,30 @@ class named_condition
template <typename L, class TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred);
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/exceptions.hpp>
#include <boost/interprocess/detail/interprocess_tester.hpp>
@@ -163,6 +165,30 @@ class named_condition_any
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{ return m_cond.timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name)

View File

@@ -151,6 +151,16 @@ class named_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Erases a named mutex from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);

View File

@@ -137,6 +137,16 @@ class named_recursive_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Erases a named recursive mutex
//!from the system
static bool remove(const char *name);

View File

@@ -151,6 +151,16 @@ class named_sharable_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
@@ -170,6 +180,11 @@ class named_sharable_mutex
//! an exception could be thrown
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
@@ -184,6 +199,11 @@ class named_sharable_mutex
//! an exception could be thrown
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
@@ -198,11 +218,26 @@ class named_sharable_mutex
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
//!Erases a named sharable mutex from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);

View File

@@ -152,6 +152,16 @@ class named_upgradable_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have exclusive ownership of the mutex.
//!Effects: The calling thread releases the exclusive ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
@@ -171,6 +181,11 @@ class named_upgradable_mutex
//! an exception could be thrown
void lock_sharable();
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
@@ -185,6 +200,11 @@ class named_upgradable_mutex
//! an exception could be thrown
bool try_lock_sharable();
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Requires: The calling thread does not own the mutex.
//!
//!Effects: The calling thread tries to acquire sharable ownership of the mutex
@@ -199,11 +219,26 @@ class named_upgradable_mutex
template<class TimePoint>
bool timed_lock_sharable(const TimePoint &abs_time);
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
{ return this->timed_lock_sharable(abs_time); }
//!Same as `timed_lock_sharable`, but this function is modeled after the
//!standard library interface.
template<class Duration> bool try_lock_shared_for(const Duration &dur)
{ return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
//!Precondition: The thread must have sharable ownership of the mutex.
//!Effects: The calling thread releases the sharable ownership of the mutex.
//!Throws: An exception derived from interprocess_exception on error.
void unlock_sharable();
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
//Upgradable locking
//!Requires: The calling thread does not own the mutex.

View File

@@ -61,6 +61,18 @@ class null_mutex
bool timed_lock(const TimePoint &)
{ return true; }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class TimePoint>
bool try_lock_until(const TimePoint &)
{ return true; }
//!Same as `timed_lock`, but this function is modeled after the
//!standard library interface.
template<class Duration>
bool try_lock_for(const Duration &)
{ return true; }
//!Simulates a mutex unlock() operation.
//!Empty function.
void unlock(){}
@@ -69,11 +81,21 @@ class null_mutex
//!Empty function.
void lock_sharable(){}
//!Same as `lock_sharable` but with a std-compatible interface
//!
void lock_shared()
{ this->lock_sharable(); }
//!Simulates a mutex try_lock_sharable() operation.
//!Equivalent to "return true;"
bool try_lock_sharable()
{ return true; }
//!Same as `try_lock_sharable` but with a std-compatible interface
//!
bool try_lock_shared()
{ return this->try_lock_sharable(); }
//!Simulates a mutex timed_lock_sharable() operation.
//!Equivalent to "return true;"
template<class TimePoint>
@@ -84,6 +106,11 @@ class null_mutex
//!Empty function.
void unlock_sharable(){}
//!Same as `unlock_sharable` but with a std-compatible interface
//!
void unlock_shared()
{ this->unlock_sharable(); }
//!Simulates a mutex lock_upgradable() operation.
//!Empty function.
void lock_upgradable(){}

View File

@@ -22,6 +22,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <pthread.h>
#include <errno.h>
#include <boost/interprocess/sync/posix/pthread_helpers.hpp>
@@ -117,6 +118,25 @@ class posix_condition
return true;
}
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, duration_to_ustime(dur)) ? cv_status::no_timeout : cv_status::timeout; }
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, duration_to_ustime(dur), pred); }
void do_wait(posix_mutex &mut);

View File

@@ -71,6 +71,13 @@ class posix_mutex
void lock();
bool try_lock();
template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
void unlock();
friend class posix_condition;

View File

@@ -56,7 +56,18 @@ class posix_named_mutex
void unlock();
void lock();
bool try_lock();
template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
template<class TimePoint>
bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration>
bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
static bool remove(const char *name);
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

View File

@@ -31,7 +31,7 @@ namespace ipcdetail {
template<class TimePoint>
inline timespec timepoint_to_timespec ( const TimePoint &tm
, typename enable_if_ptime<TimePoint>::type * = 0)
, typename enable_if_ptime<TimePoint>::type * = 0)
{
typedef typename TimePoint::date_type date_type;
typedef typename TimePoint::time_duration_type time_duration_type;
@@ -57,7 +57,7 @@ inline timespec timepoint_to_timespec (const ustime &tm)
template<class TimePoint>
inline timespec timepoint_to_timespec ( const TimePoint &tm
, typename enable_if_time_point<TimePoint>::type * = 0)
, typename enable_if_time_point<TimePoint>::type * = 0)
{
typedef typename TimePoint::duration duration_t;
duration_t d(tm.time_since_epoch());

View File

@@ -316,6 +316,38 @@ class scoped_lock
return m_locked;
}
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
//! exception. Calls try_lock_until(abs_time) on the referenced mutex.
//!Postconditions: owns() == the value returned from mutex()-> timed_lock(abs_time).
//!Notes: The scoped_lock changes from a state of not owning the mutex, to
//! owning the mutex, but only if it can obtain ownership by the specified
//! time. If the mutex_type does not support timed_lock (), this function
//! will fail at compile time if instantiated, but otherwise have no effect.*/
template<class TimePoint>
bool try_lock_until(const TimePoint& abs_time)
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_until(abs_time);
return m_locked;
}
//!Effects: If mutex() == 0 or if already locked, throws a lock_exception()
//! exception. Calls try_lock_until(abs_time) on the referenced mutex.
//!Postconditions: owns() == the value returned from mutex()-> timed_lock(abs_time).
//!Notes: The scoped_lock changes from a state of not owning the mutex, to
//! owning the mutex, but only if it can obtain ownership by the specified
//! time. If the mutex_type does not support timed_lock (), this function
//! will fail at compile time if instantiated, but otherwise have no effect.*/
template<class Duration>
bool try_lock_for(const Duration& dur)
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_for(dur);
return m_locked;
}
//!Effects: If mutex() == 0 or if not locked, throws a lock_exception()
//! exception. Calls unlock() on the referenced mutex.
//!Postconditions: owns() == false.

View File

@@ -249,6 +249,46 @@ class sharable_lock
return m_locked;
}
//!Effects: If mutex() == 0 or already locked, throws a lock_exception()
//! exception. Calls try_lock_shared_until(abs_time) on the referenced mutex.
//!Postconditions: owns() == the value returned from
//! mutex()->timed_lock_sharable(elps_time).
//!Notes: The sharable_lock changes from a state of not owning the mutex,
//! to owning the mutex, but only if it can obtain ownership within the
//! specified time interval. If the mutex_type does not support
//! timed_lock_sharable(), this function will fail at compile time if
//! instantiated, but otherwise have no effect.
//!
//!Note: Similar to timed_lock, but with a std-like interface
template<class TimePoint>
bool try_lock_until(const TimePoint& abs_time)
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_shared_until(abs_time);
return m_locked;
}
//!Effects: If mutex() == 0 or already locked, throws a lock_exception()
//! exception. Calls try_lock_shared_until(abs_time) on the referenced mutex.
//!Postconditions: owns() == the value returned from
//! mutex()->timed_lock_sharable(elps_time).
//!Notes: The sharable_lock changes from a state of not owning the mutex,
//! to owning the mutex, but only if it can obtain ownership within the
//! specified time interval. If the mutex_type does not support
//! timed_lock_sharable(), this function will fail at compile time if
//! instantiated, but otherwise have no effect.
//!
//!Note: Similar to timed_lock, but with a std-like interface
template<class Duration>
bool try_lock_for(const Duration& dur)
{
if(!mp_mutex || m_locked)
throw lock_exception();
m_locked = mp_mutex->try_lock_shared_for(dur);
return m_locked;
}
//!Effects: If mutex() == 0 or not locked, throws a lock_exception() exception.
//! Calls unlock_sharable() on the referenced mutex.
//!Postconditions: owns() == false.

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/static_assert.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/creation_tags.hpp>
@@ -151,6 +153,30 @@ class shm_named_condition
template <typename L, typename TimePoint, typename Pr>
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred);
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/static_assert.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/creation_tags.hpp>
@@ -150,6 +152,30 @@ class shm_named_condition_any
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->internal_cond().timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface.
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts.
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
//!Same as `timed_wait`, but this function is modeled after the
//!standard library interface and uses relative timeouts
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
//!Erases a named condition from the system.
//!Returns false on error. Never throws.
template <class CharT>

View File

@@ -120,6 +120,12 @@ class shm_named_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
//!Erases a named mutex from the system.
//!Returns false on error. Never throws.
static bool remove(const char *name);

View File

@@ -115,6 +115,12 @@ class shm_named_recursive_mutex
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
//!Erases a named recursive mutex
//!from the system
static bool remove(const char *name);

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/spin/mutex.hpp>
#include <boost/interprocess/detail/atomic.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
@@ -63,6 +65,24 @@ class spin_condition
void notify_all()
{ this->notify(NOTIFY_ALL); }
template <typename L>
void wait(L& lock)
{
if (!lock)
throw lock_exception();
this->do_timed_wait_impl<false>(0, *lock.mutex());
}
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
{
if (!lock)
throw lock_exception();
while (!pred())
this->do_timed_wait_impl<false>(0, *lock.mutex());
}
template <typename L, typename TimePoint>
bool timed_wait(L& lock, const TimePoint &abs_time)
{
@@ -93,23 +113,21 @@ class spin_condition
return true;
}
template <typename L>
void wait(L& lock)
{
if (!lock)
throw lock_exception();
this->do_timed_wait_impl<false>(0, *lock.mutex());
}
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
{
if (!lock)
throw lock_exception();
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
while (!pred())
this->do_timed_wait_impl<false>(0, *lock.mutex());
}
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, duration_to_ustime(dur)); }
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, duration_to_ustime(dur), pred); }
private:

View File

@@ -42,7 +42,15 @@ class spin_mutex
void lock();
bool try_lock();
template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
void unlock();
void take_ownership(){}
private:

View File

@@ -61,7 +61,15 @@ class spin_recursive_mutex
void lock();
bool try_lock();
template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
template<class TimePoint>
bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
void unlock();
void take_ownership();
private:

View File

@@ -22,6 +22,7 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/exceptions.hpp>
@@ -57,6 +58,15 @@ class winapi_condition
void notify_all()
{ m_condition_data.notify_all(); }
template <typename L>
void wait(L& lock)
{ m_condition_data.wait(lock); }
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
{ m_condition_data.wait(lock, pred); }
template <typename L, typename TimePoint>
bool timed_wait(L& lock, const TimePoint &abs_time)
{ return m_condition_data.timed_wait(lock, abs_time); }
@@ -65,13 +75,21 @@ class winapi_condition
bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
{ return m_condition_data.timed_wait(lock, abs_time, pred); }
template <typename L>
void wait(L& lock)
{ m_condition_data.wait(lock); }
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
{ m_condition_data.wait(lock, pred); }
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, duration_to_ustime(dur)); }
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, duration_to_ustime(dur), pred); }
private:

View File

@@ -44,6 +44,13 @@ class winapi_mutex
void lock();
bool try_lock();
template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
void unlock();
void take_ownership(){};

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/sync/windows/named_condition_any.hpp>
namespace boost {

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/sync/cv_status.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/permissions.hpp>
#include <boost/interprocess/detail/interprocess_tester.hpp>
@@ -156,6 +158,22 @@ class winapi_named_condition_any
void wait(L& lock, Pr pred)
{ m_condition_data.wait(lock, pred); }
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{ return this->timed_wait(lock, abs_time) ? cv_status::no_timeout : cv_status::timeout; }
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{ return this->timed_wait(lock, abs_time, pred); }
template <typename L, class Duration>
cv_status wait_for(L& lock, const Duration &dur)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur)); }
template <typename L, class Duration, typename Pr>
bool wait_for(L& lock, const Duration &dur, Pr pred)
{ return this->wait_until(lock, ipcdetail::duration_to_ustime(dur), pred); }
static bool remove(const char *name)
{ return windows_named_sync::remove(name); }

View File

@@ -66,6 +66,12 @@ class winapi_named_mutex
bool try_lock();
template<class TimePoint> bool timed_lock(const TimePoint &abs_time);
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(duration_to_ustime(dur)); }
static bool remove(const char *name);
static bool remove(const wchar_t *name);

View File

@@ -87,54 +87,7 @@ struct cond_predicate
int _val;
};
template <class Condition, class Mutex>
void condition_test_waits(condition_test_data<Condition, Mutex>* data)
{
boost::interprocess::scoped_lock<Mutex>
lock(data->mutex);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
// Test wait.
while (data->notified != 1)
data->condition.wait(lock);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 1);
data->awoken++;
data->condition.notify_one();
// Test predicate wait.
data->condition.wait(lock, cond_predicate(data->notified, 2));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 2);
data->awoken++;
data->condition.notify_one();
// Test timed_wait
while (data->notified != 3)
data->condition.timed_wait(lock, ptime_delay(5));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 3);
data->awoken++;
data->condition.notify_one();
// Test predicate timed_wait.
cond_predicate pred(data->notified, 4);
bool ret = data->condition.timed_wait(lock, boost_systemclock_delay(5), pred);
BOOST_INTERPROCESS_CHECK(ret);(void)ret;
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(pred());
BOOST_INTERPROCESS_CHECK(data->notified == 4);
data->awoken++;
data->condition.notify_one();
// Test timed_wait
while (data->notified != 5)
data->condition.timed_wait(lock, std_systemclock_delay(5));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 5);
data->awoken++;
data->condition.notify_one();
}
template <class Condition, class Mutex>
void do_test_condition_notify_one()
@@ -185,6 +138,141 @@ void do_test_condition_notify_all()
BOOST_INTERPROCESS_CHECK(data.awoken == NUMTHREADS);
}
template <class Condition, class Mutex>
void do_test_condition_waits_step( condition_test_data<Condition, Mutex> &data
, boost::interprocess::scoped_lock<Mutex> &lock
, int awoken)
{
boost::interprocess::ipcdetail::thread_sleep(1000);
data.notified++;
data.condition.notify_one();
while (data.awoken != awoken)
data.condition.wait(lock);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data.awoken == awoken);
}
template <class Condition, class Mutex>
void condition_test_waits(condition_test_data<Condition, Mutex>* data)
{
boost::interprocess::scoped_lock<Mutex>
lock(data->mutex);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
// Test wait.
while (data->notified != 1)
data->condition.wait(lock);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 1);
data->awoken++;
data->condition.notify_one();
// Test predicate wait.
data->condition.wait(lock, cond_predicate(data->notified, 2));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 2);
data->awoken++;
data->condition.notify_one();
// Test timed_wait
while (data->notified != 3)
data->condition.timed_wait(lock, ptime_delay(5));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 3);
data->awoken++;
data->condition.notify_one();
// Test predicate timed_wait.
{
bool ret = data->condition.timed_wait(lock, boost_systemclock_delay(5), cond_predicate (data->notified, 4));
BOOST_INTERPROCESS_CHECK(ret);(void)ret;
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 4);
data->awoken++;
data->condition.notify_one();
}
// Test timed_wait
while (data->notified != 5)
data->condition.timed_wait(lock, std_systemclock_delay(5));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 5);
data->awoken++;
data->condition.notify_one();
// Test wait_until
while (data->notified != 6)
data->condition.wait_until(lock, ptime_delay(5));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 6);
data->awoken++;
data->condition.notify_one();
// Test predicate wait_until.
{
bool ret = data->condition.wait_until(lock, boost_systemclock_delay(5), cond_predicate (data->notified, 7));
BOOST_INTERPROCESS_CHECK(ret);(void)ret;
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 7);
data->awoken++;
data->condition.notify_one();
}
// Test wait_for
while (data->notified != 8)
data->condition.wait_for(lock, ptime_seconds(5));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 8);
data->awoken++;
data->condition.notify_one();
// Test predicate wait_for.
{
bool ret = data->condition.wait_for(lock, ptime_seconds(5), cond_predicate (data->notified, 9));
BOOST_INTERPROCESS_CHECK(ret);(void)ret;
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 9);
data->awoken++;
data->condition.notify_one();
}
// Test wait_for
while (data->notified != 10)
data->condition.wait_for(lock, boost_systemclock_seconds(5));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 10);
data->awoken++;
data->condition.notify_one();
// Test predicate wait_for.
{
bool ret = data->condition.wait_for(lock, boost_systemclock_seconds(5), cond_predicate (data->notified, 11));
BOOST_INTERPROCESS_CHECK(ret);(void)ret;
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 11);
data->awoken++;
data->condition.notify_one();
}
// Test wait_for
while (data->notified != 12)
data->condition.wait_for(lock, std_systemclock_seconds(5));
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 12);
data->awoken++;
data->condition.notify_one();
// Test predicate wait_for.
{
bool ret = data->condition.wait_for(lock, std_systemclock_seconds(5), cond_predicate (data->notified, 13));
BOOST_INTERPROCESS_CHECK(ret);(void)ret;
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data->notified == 13);
data->awoken++;
data->condition.notify_one();
}
}
template <class Condition, class Mutex>
void do_test_condition_waits()
{
@@ -197,50 +285,14 @@ void do_test_condition_waits()
lock(data.mutex);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
boost::interprocess::ipcdetail::thread_sleep(1000);
data.notified++;
data.condition.notify_one();
while (data.awoken != 1)
data.condition.wait(lock);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data.awoken == 1);
boost::interprocess::ipcdetail::thread_sleep(1000);
data.notified++;
data.condition.notify_one();
while (data.awoken != 2)
data.condition.wait(lock);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data.awoken == 2);
boost::interprocess::ipcdetail::thread_sleep(1000);
data.notified++;
data.condition.notify_one();
while (data.awoken != 3)
data.condition.wait(lock);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data.awoken == 3);
boost::interprocess::ipcdetail::thread_sleep(1000);
data.notified++;
data.condition.notify_one();
while (data.awoken != 4)
data.condition.wait(lock);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data.awoken == 4);
boost::interprocess::ipcdetail::thread_sleep(1000);
data.notified++;
data.condition.notify_one();
while (data.awoken != 5)
data.condition.wait(lock);
BOOST_INTERPROCESS_CHECK(lock ? true : false);
BOOST_INTERPROCESS_CHECK(data.awoken == 5);
for(int i = 1; i <= 13; ++i)
do_test_condition_waits_step(data, lock, i);
}
boost::interprocess::ipcdetail::thread_join(thread);
BOOST_INTERPROCESS_CHECK(data.awoken == 5);
BOOST_INTERPROCESS_CHECK(data.awoken == 13);
}
/*
//Message queue simulation test
template <class Condition>

View File

@@ -70,7 +70,7 @@ int main ()
mapping.swap(move_assign);
}
//test::test_all_lock<file_lock_lock_test_wrapper>();
test::test_all_lock<file_lock_lock_test_wrapper>();
//test::test_all_mutex<file_lock_lock_test_wrapper>();
//test::test_all_sharable_mutex<file_lock_lock_test_wrapper>();
std::remove(get_filename().c_str());

View File

@@ -224,13 +224,32 @@ void try_lock_and_sleep(void *arg, M &sm)
}
}
enum ETimedLockFlags
{
TimedLock = 0,
TryLockUntil = 1,
TryLockFor = 2,
ETimedLockFlagsMax
};
template<typename M>
void timed_lock_and_sleep(void *arg, M &sm)
{
data<M> *pdata = static_cast<data<M>*>(arg);
boost::interprocess::scoped_lock<M>
l (sm, boost::interprocess::defer_lock);
if (l.timed_lock(std_systemclock_delay(pdata->m_secs))){
bool r = false;
if(pdata->m_flags == (int)TimedLock){
r = l.timed_lock(std_systemclock_delay(pdata->m_secs));
}
else if (pdata->m_flags == (int)TryLockUntil) {
r = l.try_lock_until(ptime_delay(pdata->m_secs));
}
else if (pdata->m_flags == (int)TryLockFor) {
r = l.try_lock_for(boost_systemclock_seconds(pdata->m_secs));
}
if (r){
boost::interprocess::ipcdetail::thread_sleep((1000*2*BaseSeconds));
++shared_val;
pdata->m_value = shared_val;
@@ -336,33 +355,35 @@ void test_mutex_try_lock()
template<typename M>
void test_mutex_timed_lock()
{
shared_val = 0;
for (int flag = 0; flag != (int)ETimedLockFlagsMax; ++flag)
{
shared_val = 0;
M mtx, m2;
M mtx, m2;
data<M> d1(1, 2*BaseSeconds);
data<M> d2(2, 2*BaseSeconds);
data<M> d1(1, 2*BaseSeconds, flag);
data<M> d2(2, 2*BaseSeconds, flag);
// Locker one launches, holds the lock for 2*BaseSeconds seconds.
boost::interprocess::ipcdetail::OS_thread_t tm1;
boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter<M>(&timed_lock_and_sleep, &d1, mtx));
// Locker one launches, holds the lock for 2*BaseSeconds seconds.
boost::interprocess::ipcdetail::OS_thread_t tm1;
boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter<M>(&timed_lock_and_sleep, &d1, mtx));
//Wait 1*BaseSeconds
boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds));
//Wait 1*BaseSeconds
boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds));
// Locker two launches, holds the lock for 2*BaseSeconds seconds.
boost::interprocess::ipcdetail::OS_thread_t tm2;
boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter<M>(&timed_lock_and_sleep, &d2, mtx));
// Locker two launches, holds the lock for 2*BaseSeconds seconds.
boost::interprocess::ipcdetail::OS_thread_t tm2;
boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter<M>(&timed_lock_and_sleep, &d2, mtx));
//Wait completion
boost::interprocess::ipcdetail::thread_join(tm1);
boost::interprocess::ipcdetail::thread_join(tm2);
//Wait completion
boost::interprocess::ipcdetail::thread_join(tm1);
boost::interprocess::ipcdetail::thread_join(tm2);
//Both should succeed locking
BOOST_INTERPROCESS_CHECK(d1.m_value == 1);
BOOST_INTERPROCESS_CHECK(d2.m_value == 2);
//Both should succeed locking
BOOST_INTERPROCESS_CHECK(d1.m_value == 1);
BOOST_INTERPROCESS_CHECK(d2.m_value == 2);
}
}
template <typename M>

View File

@@ -100,6 +100,20 @@ class named_condition_test_wrapper
return NamedCondition::timed_wait(internal_lock, abs_time, pred);
}
template <typename L, class TimePoint>
cv_status wait_until(L& lock, const TimePoint &abs_time)
{
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
return NamedCondition::wait_until(internal_lock, abs_time);
}
template <typename L, class TimePoint, typename Pr>
bool wait_until(L& lock, const TimePoint &abs_time, Pr pred)
{
ipcdetail::internal_mutex_lock<L> internal_lock(lock);
return NamedCondition::wait_until(internal_lock, abs_time, pred);
}
static int count;
};

View File

@@ -21,6 +21,8 @@
#include <boost/interprocess/sync/windows/named_semaphore.hpp>
#endif
#include <boost/interprocess/detail/timed_utils.hpp>
using namespace boost::interprocess;
static const std::size_t RecSemCount = 100;
@@ -61,6 +63,12 @@ class lock_test_wrapper
bool timed_lock(const TimePoint &pt)
{ return this->timed_wait(pt); }
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(boost::interprocess::ipcdetail::duration_to_ustime(dur)); }
void unlock()
{ this->post(); }
};

View File

@@ -37,6 +37,12 @@ class semaphore_test_wrapper
bool timed_lock(const TimePoint &pt)
{ return this->timed_wait(pt); }
template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
{ return this->timed_lock(abs_time); }
template<class Duration> bool try_lock_for(const Duration &dur)
{ return this->timed_lock(boost::interprocess::ipcdetail::duration_to_ustime(dur)); }
void unlock()
{ this->post(); }

View File

@@ -81,34 +81,6 @@ void try_shared(void *arg, SM &sm)
}
}
template<typename SM>
void timed_exclusive(void *arg, SM &sm)
{
data<SM> *pdata = static_cast<data<SM>*>(arg);
boost::posix_time::ptime pt(ptime_delay(pdata->m_secs));
boost::interprocess::scoped_lock<SM>
l (sm, boost::interprocess::defer_lock);
if (l.timed_lock(pt)){
boost::interprocess::ipcdetail::thread_sleep((1000*3*BaseSeconds));
shared_val += 10;
pdata->m_value = shared_val;
}
}
template<typename SM>
void timed_shared(void *arg, SM &sm)
{
data<SM> *pdata = static_cast<data<SM>*>(arg);
boost::interprocess::sharable_lock<SM>
l(sm, boost::interprocess::defer_lock);
if (l.timed_lock(boost_systemclock_delay(pdata->m_secs))){
if(pdata->m_secs){
boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs*BaseSeconds));
}
pdata->m_value = shared_val;
}
}
template<typename SM>
void test_plain_sharable_mutex()
{
@@ -223,50 +195,104 @@ void test_try_sharable_mutex()
BOOST_INTERPROCESS_CHECK(e2.m_value == -1); // Try would return w/o waiting
}
template<typename SM>
void timed_exclusive(void *arg, SM &sm)
{
data<SM> *pdata = static_cast<data<SM>*>(arg);
boost::interprocess::scoped_lock<SM>
l (sm, boost::interprocess::defer_lock);
bool r = false;
if(pdata->m_flags == (int)TimedLock){
r = l.timed_lock(std_systemclock_delay(pdata->m_secs));
}
else if (pdata->m_flags == (int)TryLockUntil) {
r = l.try_lock_until(ptime_delay(pdata->m_secs));
}
else if (pdata->m_flags == (int)TryLockFor) {
r = l.try_lock_for(boost_systemclock_seconds(pdata->m_secs));
}
if (r){
boost::interprocess::ipcdetail::thread_sleep((1000*3*BaseSeconds));
shared_val += 10;
pdata->m_value = shared_val;
}
}
template<typename SM>
void timed_shared(void *arg, SM &sm)
{
data<SM> *pdata = static_cast<data<SM>*>(arg);
boost::interprocess::sharable_lock<SM>
l(sm, boost::interprocess::defer_lock);
bool r = false;
if(pdata->m_flags == (int)TimedLock){
r = l.timed_lock(std_systemclock_delay(pdata->m_secs));
}
else if (pdata->m_flags == (int)TryLockUntil) {
r = l.try_lock_until(ptime_delay(pdata->m_secs));
}
else if (pdata->m_flags == (int)TryLockFor) {
r = l.try_lock_for(boost_systemclock_seconds(pdata->m_secs));
}
if (r){
if(pdata->m_secs){
boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs*BaseSeconds));
}
pdata->m_value = shared_val;
}
}
template<typename SM>
void test_timed_sharable_mutex()
{
SM mtx;
data<SM> s1(1,1*BaseSeconds);
data<SM> s2(2,3*BaseSeconds);
data<SM> e1(3,3*BaseSeconds);
data<SM> e2(4,1*BaseSeconds);
for (int flag = 0; flag != (int)ETimedLockFlagsMax; ++flag)
{
SM mtx;
data<SM> s1(1,1*BaseSeconds, flag);
data<SM> s2(2,3*BaseSeconds, flag);
data<SM> e1(3,3*BaseSeconds, flag);
data<SM> e2(4,1*BaseSeconds, flag);
// We begin with some specialized tests for "timed" behavior
// We begin with some specialized tests for "timed" behavior
shared_val = 0;
shared_val = 0;
// Writer one will hold the lock for 3*BaseSeconds seconds.
boost::interprocess::ipcdetail::OS_thread_t tw1;
boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter<SM>(timed_exclusive,&e1,mtx));
// Writer one will hold the lock for 3*BaseSeconds seconds.
boost::interprocess::ipcdetail::OS_thread_t tw1;
boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter<SM>(timed_exclusive,&e1,mtx));
boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds));
// Writer two will "clearly" try for the lock after the readers
// have tried for it. Writer will wait up 1*BaseSeconds seconds for the lock.
// This write will fail.
boost::interprocess::ipcdetail::OS_thread_t tw2;
boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter<SM>(timed_exclusive,&e2,mtx));
boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds));
// Writer two will "clearly" try for the lock after the readers
// have tried for it. Writer will wait up 1*BaseSeconds seconds for the lock.
// This write will fail.
boost::interprocess::ipcdetail::OS_thread_t tw2;
boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter<SM>(timed_exclusive,&e2,mtx));
// Readers one and two will "clearly" try for the lock after writer
// one already holds it. 1st reader will wait 1*BaseSeconds seconds, and will fail
// to get the lock. 2nd reader will wait 3*BaseSeconds seconds, and will get
// the lock.
// Readers one and two will "clearly" try for the lock after writer
// one already holds it. 1st reader will wait 1*BaseSeconds seconds, and will fail
// to get the lock. 2nd reader will wait 3*BaseSeconds seconds, and will get
// the lock.
boost::interprocess::ipcdetail::OS_thread_t thr1;
boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter<SM>(timed_shared,&s1,mtx));
boost::interprocess::ipcdetail::OS_thread_t thr1;
boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter<SM>(timed_shared,&s1,mtx));
boost::interprocess::ipcdetail::OS_thread_t thr2;
boost::interprocess::ipcdetail::thread_launch(thr2, thread_adapter<SM>(timed_shared,&s2,mtx));
boost::interprocess::ipcdetail::OS_thread_t thr2;
boost::interprocess::ipcdetail::thread_launch(thr2, thread_adapter<SM>(timed_shared,&s2,mtx));
boost::interprocess::ipcdetail::thread_join(tw1);
boost::interprocess::ipcdetail::thread_join(thr1);
boost::interprocess::ipcdetail::thread_join(thr2);
boost::interprocess::ipcdetail::thread_join(tw2);
boost::interprocess::ipcdetail::thread_join(tw1);
boost::interprocess::ipcdetail::thread_join(thr1);
boost::interprocess::ipcdetail::thread_join(thr2);
boost::interprocess::ipcdetail::thread_join(tw2);
BOOST_INTERPROCESS_CHECK(e1.m_value == 10);
BOOST_INTERPROCESS_CHECK(s1.m_value == -1);
BOOST_INTERPROCESS_CHECK(s2.m_value == 10);
BOOST_INTERPROCESS_CHECK(e2.m_value == -1);
BOOST_INTERPROCESS_CHECK(e1.m_value == 10);
BOOST_INTERPROCESS_CHECK(s1.m_value == -1);
BOOST_INTERPROCESS_CHECK(s2.m_value == 10);
BOOST_INTERPROCESS_CHECK(e2.m_value == -1);
}
}
template<typename SM>

View File

@@ -50,19 +50,31 @@ inline boost::posix_time::ptime ptime_delay(int secs, int msecs=0, int nsecs = 0
return cur += boost::posix_time::time_duration(0, 0, secs, count);
}
inline boost::posix_time::time_duration ptime_seconds(int secs)
{ return boost::posix_time::time_duration(0, 0, secs); }
inline boost::chrono::system_clock::time_point boost_systemclock_delay(int secs)
{ return boost::chrono::system_clock::now() + boost::chrono::seconds(secs); }
inline boost::chrono::seconds boost_systemclock_seconds(int secs)
{ return boost::chrono::seconds(secs); }
#if !defined(BOOST_NO_CXX11_HDR_CHRONO)
//Use std chrono if available
inline std::chrono::system_clock::time_point std_systemclock_delay(int secs)
{ return std::chrono::system_clock::now() + std::chrono::seconds(secs); }
inline std::chrono::seconds std_systemclock_seconds(int secs)
{ return std::chrono::seconds(secs); }
#else
//Otherwise use boost chrono
inline boost::chrono::system_clock::time_point std_systemclock_delay(int secs)
{ return boost_systemclock_delay(secs); }
inline boost::chrono::seconds std_systemclock_seconds(int secs)
{ return boost::chrono::seconds(secs); }
#endif
@@ -83,13 +95,14 @@ class thread_adapter
template <typename P>
struct data
{
explicit data(int id, int secs=0)
: m_id(id), m_value(-1), m_secs(secs), m_error(no_error)
explicit data(int id, int secs=0, int flags = 0)
: m_id(id), m_value(-1), m_secs(secs), m_error(no_error), m_flags(flags)
{}
int m_id;
int m_value;
int m_secs;
error_code_t m_error;
int m_flags;
};
int shared_val = 0;