Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81084 - in trunk: boost/thread libs/thread/example
From: vicente.botet_at_[hidden]
Date: 2012-10-28 21:03:32


Author: viboes
Date: 2012-10-28 21:03:31 EDT (Sun, 28 Oct 2012)
New Revision: 81084
URL: http://svn.boost.org/trac/boost/changeset/81084

Log:
Thread: Added strict locks
Added:
   trunk/boost/thread/lock_concepts.hpp (contents, props changed)
   trunk/boost/thread/lock_traits.hpp (contents, props changed)
   trunk/boost/thread/strict_lock.hpp (contents, props changed)
   trunk/libs/thread/example/strict_lock.cpp (contents, props changed)

Added: trunk/boost/thread/lock_concepts.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/lock_concepts.hpp 2012-10-28 21:03:31 EDT (Sun, 28 Oct 2012)
@@ -0,0 +1,158 @@
+// (C) Copyright 2012 Vicente Botet
+//
+// 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_THREAD_LOCK_CONCEPTS_HPP
+#define BOOST_THREAD_LOCK_CONCEPTS_HPP
+
+#include <boost/thread/lock_traits.hpp>
+#include <boost/thread/lock_options.hpp>
+#include <boost/thread/lockable_concepts.hpp>
+#include <boost/thread/exceptions.hpp>
+
+#include <boost/chrono/chrono.hpp>
+#include <boost/concept_check.hpp>
+
+namespace boost
+{
+
+ /**
+ * BasicLock object supports the basic features
+ * required to delimit a critical region
+ * Supports the basic lock, unlock and try_lock functions and
+ * defines the lock traits
+ */
+
+ template <typename Lk>
+ struct BasicLock
+ {
+ typedef typename Lk::mutex_type mutex_type;
+ void cvt_mutex_ptr(mutex_type*);
+ BOOST_CONCEPT_ASSERT(( BasicLockable<mutex_type> ));
+
+ BOOST_CONCEPT_USAGE(BasicLock)
+ {
+ const Lk l1(mtx);
+ Lk l2(mtx, defer_lock);
+ Lk l3(mtx, adopt_lock);
+ Lk l4(( Lk()));
+ // BUG Lk l5(( boost::move(l1)));
+ cvt_mutex_ptr(l1.mutex());
+ if (l1.owns_lock()) return;
+ if (l1) return;
+ if (!l1) return;
+
+ l2.lock();
+ l2.unlock();
+ l2.release();
+
+ }
+ mutex_type mtx;
+ }
+ ;
+
+ template <typename Lk>
+ struct Lock
+ {
+ BOOST_CONCEPT_ASSERT(( BasicLock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+ BOOST_CONCEPT_ASSERT(( Lockable<mutex_type> ));
+
+ BOOST_CONCEPT_USAGE(Lock)
+ {
+ Lk l1(mtx, try_to_lock);
+ if (l1.try_lock()) return;
+ }
+ mutex_type mtx;
+ };
+
+ template <typename Lk>
+ struct TimedLock
+ {
+ BOOST_CONCEPT_ASSERT(( Lock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+ BOOST_CONCEPT_ASSERT(( TimedLockable<mutex_type> ));
+
+ BOOST_CONCEPT_USAGE(TimedLock)
+ {
+ Lk l1(mtx, t);
+ Lk l2(mtx, d);
+ if (l1.try_lock_until(t)) return;
+ if (l1.try_lock_for(d)) return;
+ }
+ mutex_type mtx;
+ boost::chrono::system_clock::time_point t;
+ boost::chrono::system_clock::duration d;
+ };
+
+ template <typename Lk>
+ struct UniqueLock
+ {
+ BOOST_CONCEPT_ASSERT(( TimedLock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+
+ BOOST_CONCEPT_USAGE(UniqueLock)
+ {
+
+ }
+ mutex_type mtx;
+ };
+
+ template <typename Lk>
+ struct SharedLock
+ {
+ BOOST_CONCEPT_ASSERT(( TimedLock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+
+ BOOST_CONCEPT_USAGE(SharedLock)
+ {
+ }
+ mutex_type mtx;
+
+ };
+
+ template <typename Lk>
+ struct UpgradeLock
+ {
+ BOOST_CONCEPT_ASSERT(( SharedLock<Lk> ));
+ typedef typename Lk::mutex_type mutex_type;
+
+ BOOST_CONCEPT_USAGE(UpgradeLock)
+ {
+ }
+ mutex_type mtx;
+ };
+
+ /**
+ * An StrictLock is a scoped lock guard ensuring the mutex is locked on the
+ * scope of the lock, by locking the mutex on construction and unlocking it on
+ * destruction.
+ *
+ * Essentially, a StrictLock's role is only to live on the stack as an
+ * automatic variable. strict_lock must adhere to a non-copy and non-alias
+ * policy. StrictLock disables copying by making the copy constructor and the
+ * assignment operator private. While we're at it, let's disable operator new
+ * and operator delete; strict locks are not intended to be allocated on the
+ * heap. StrictLock avoids aliasing by using a slightly less orthodox and
+ * less well-known technique: disable address taking.
+ */
+
+ template <typename Lk>
+ struct StrictLock
+ {
+ typedef typename Lk::mutex_type mutex_type;
+ BOOST_CONCEPT_ASSERT(( BasicLockable<mutex_type> ));
+ BOOST_STATIC_ASSERT(( is_strict_lock<Lk>::value));
+
+ BOOST_CONCEPT_USAGE( StrictLock)
+ {
+ if (l1.is_locking(&mtx)) return;
+ }
+ const Lk &l1;
+ mutex_type mtx;
+
+ };
+
+}
+#endif

Added: trunk/boost/thread/lock_traits.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/lock_traits.hpp 2012-10-28 21:03:31 EDT (Sun, 28 Oct 2012)
@@ -0,0 +1,42 @@
+// 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)
+// (C) Copyright 2009-2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_LOCK_TRAITS_HPP
+#define BOOST_THREAD_LOCK_TRAITS_HPP
+
+#include <boost/thread/detail/config.hpp>
+//#include <boost/thread/detail/move.hpp>
+//#include <boost/thread/exceptions.hpp>
+//
+//#ifdef BOOST_THREAD_USES_CHRONO
+//#include <boost/chrono/time_point.hpp>
+//#include <boost/chrono/duration.hpp>
+//#endif
+
+#include <boost/type_traits/integral_constant.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+/**
+ * An strict lock is a lock ensuring the mutex is locked on the scope of the lock
+ * There is no single way to define a strict lock as the strict_lock and
+ * nesteed_strict_lock shows. So we need a metafunction that states if a
+ * lock is a strict lock "sur parolle".
+ */
+
+template <typename Lock>
+struct is_strict_lock_sur_parolle : false_type {};
+
+
+template <typename Lock>
+struct is_strict_lock : is_strict_lock_sur_parolle<Lock> {};
+
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif

Added: trunk/boost/thread/strict_lock.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/strict_lock.hpp 2012-10-28 21:03:31 EDT (Sun, 28 Oct 2012)
@@ -0,0 +1,185 @@
+// 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)
+// (C) Copyright 2008-2009,2012 Vicente J. Botet Escriba
+
+#ifndef BOOST_THREAD_STRICT_LOCK_HPP
+#define BOOST_THREAD_STRICT_LOCK_HPP
+
+#include <boost/thread/detail/delete.hpp>
+#include <boost/thread/lock_options.hpp>
+#include <boost/thread/is_locked_by_this_thread.hpp>
+#include <boost/thread/lock_traits.hpp>
+#include <boost/thread/lockable_traits.hpp>
+#include <boost/thread/lockable_concepts.hpp>
+#include <boost/thread/lock_concepts.hpp>
+#include <boost/thread/exceptions.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+
+ //[strict_lock
+ template <typename Lockable>
+ class strict_lock
+ {
+
+ BOOST_CONCEPT_ASSERT(( BasicLockable<Lockable> ));
+ public:
+ typedef Lockable mutex_type;
+
+ // construct/copy/destroy:
+
+ BOOST_THREAD_NO_COPYABLE( strict_lock)
+
+ /**
+ * Constructor from a mutex reference.
+ *
+ * @param mtx the mutex to lock.
+ *
+ * __Effects: Stores a reference to the mutex to lock and locks it.
+ * __Throws: Any exception BasicMutex::lock() can throw.
+ */
+ explicit strict_lock(mutex_type& mtx) :
+ mtx_(mtx)
+ {
+ mtx.lock();
+ } /*< locks on construction >*/
+
+ /**
+ * Destructor
+ *
+ * __Effects: unlocks the stored mutex.
+ *
+ * __Throws
+ */
+ ~strict_lock()
+ {
+ mtx_.unlock();
+ } /*< unlocks on destruction >*/
+
+
+ // observers
+ /**
+ * @return the owned mutex.
+ */
+ const mutex_type* mutex() const BOOST_NOEXCEPT
+ {
+ return &mtx_;
+ }
+
+ /**
+ * @return whether if this lock is locking that mutex.
+ */
+ bool is_locking(mutex_type* l) const BOOST_NOEXCEPT
+ {
+ return l == mutex();
+ } /*< strict locks specific function >*/
+
+ //BOOST_ADRESS_OF_DELETE(strict_lock) /*< disable aliasing >*/
+ //BOOST_HEAP_ALLOCATION_DELETE(strict_lock) /*< disable heap allocation >*/
+
+ /*< no possibility to unlock >*/
+
+ private:
+ mutex_type& mtx_;
+ };
+ //]
+ template <typename Lockable>
+ struct is_strict_lock_sur_parolle<strict_lock<Lockable> > : true_type
+ {
+ };
+
+ /**
+ * A nested strict lock is a scoped lock guard ensuring the mutex is locked on its
+ * scope, by taking ownership of an nesting lock, and locking the mutex on construction if not already locked
+ * and restoring the ownership to the nesting lock on destruction.
+ */
+ //[nested_strict_lock
+ template <typename Lock>
+ class nested_strict_lock
+ {
+ BOOST_CONCEPT_ASSERT(( BasicLock<Lock> )); /*< The Lock must be a movable lock >*/
+ public:
+ typedef typename Lock::mutex_type mutex_type; /*< Name the lockable type locked by Lock >*/
+
+ BOOST_THREAD_NO_COPYABLE( nested_strict_lock)
+
+ /**
+ * Constructor from a nesting @c Lock.
+ *
+ * @param lk the nesting lock
+ *
+ * __Requires: <c>lk.mutex() != null_ptr</c>
+ * __Effects: Stores the reference to the lock parameter and takes ownership on it.
+ * If the lock doesn't owns the mutex @mtx lock it.
+ * __Postconditions: @c is_locking()
+ * __StrongException
+ * __Throws:
+ *
+ * - lock_error when BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined and lk.mutex() == null_ptr
+ *
+ * - Any exception that @c lk.lock() can throw.
+ *
+ */
+ nested_strict_lock(Lock& lk) :
+ lk_(lk) /*< Store reference to lk >*/
+ {
+#ifdef BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/
+ if (lk.mutex() == 0)
+ {
+ throw_exception( lock_error() );
+ }
+#endif
+ if (!lk.owns_lock()) lk.lock(); /*< ensures it is locked >*/
+ tmp_lk_ = move(lk); /*< Move ownership to temporary lk >*/
+ }
+
+ /**
+ * Destructor
+ *
+ * __Effects: Restores ownership to the nesting lock.
+ */
+ ~nested_strict_lock()BOOST_NOEXCEPT
+ {
+ lk_ = move(tmp_lk_); /*< Move ownership to nesting lock >*/
+ }
+
+ // observers
+
+ /**
+ * return @c the owned mutex.
+ */
+ const mutex_type* mutex() const BOOST_NOEXCEPT
+ {
+ return tmp_lk_.mutex();
+ }
+
+ /**
+ * @return whether if this lock is locking that mutex.
+ */
+ bool is_locking(mutex_type* l) const BOOST_NOEXCEPT
+ {
+ return l == mutex();
+ }
+
+ //BOOST_ADRESS_OF_DELETE(nested_strict_lock)
+ //BOOST_HEAP_ALLOCATEION_DELETE(nested_strict_lock)
+
+ private:
+ Lock& lk_;
+ Lock tmp_lk_;
+ };
+ //]
+
+ template <typename Lock>
+ struct is_strict_lock_sur_parolle<nested_strict_lock<Lock> > : true_type
+ {
+ };
+
+}
+#include <boost/config/abi_suffix.hpp>
+
+#endif

Added: trunk/libs/thread/example/strict_lock.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/example/strict_lock.cpp 2012-10-28 21:03:31 EDT (Sun, 28 Oct 2012)
@@ -0,0 +1,40 @@
+// Copyright (C) 2012 Vicente Botet
+//
+// 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)
+
+#define BOOST_THREAD_VERSION 4
+
+#include <boost/thread/lock_traits.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/strict_lock.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <iostream>
+
+
+BOOST_STATIC_ASSERT(boost::is_strict_lock<boost::strict_lock<boost::mutex> >::value);
+BOOST_CONCEPT_ASSERT(( boost::BasicLockable<boost::mutex> ));
+BOOST_CONCEPT_ASSERT(( boost::StrictLock<boost::strict_lock<boost::mutex> > ));
+
+int main()
+{
+ {
+ boost::mutex mtx;
+ boost::strict_lock<boost::mutex> lk(mtx);
+ std::cout << __FILE__ << std::endl;
+ }
+ {
+ boost::timed_mutex mtx;
+ boost::unique_lock<boost::timed_mutex> lk(mtx);
+ boost::nested_strict_lock<boost::unique_lock<boost::timed_mutex> > nlk(lk);
+ std::cout << __FILE__ << std::endl;
+ }
+ {
+ boost::mutex mtx;
+ boost::unique_lock<boost::mutex> lk(mtx, boost::defer_lock);
+ boost::nested_strict_lock<boost::unique_lock<boost::mutex> > nlk(lk);
+ std::cout << __FILE__ << std::endl;
+ }
+ return 0;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk