
AMDG Phil Endecott <spam_from_boost_dev <at> chezphil.org> writes:
Hi Frank,
Thanks; yes, I think this sort of thing would also be a useful addition to Boost. The syntax that I presented had the advantage that
a.push_back(123); a.push_back(321);
can have a single lock around both operations, while Bjarne's wrapper would lock and unlock for each one. Also, I'm not sure whether his could be extended to offer read locks for some operations and write locks for others.
Here's something along these lines that I wrote a while back. In Christ, Steven Watanabe // locked_object.hpp // // Copyright (c) 2006-2007 // Steven Watanabe // // 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 LOCKED_OBJECT_H_INCLUDED #define LOCKED_OBJECT_H_INCLUDED #include <cassert> #include <iterator> #include <algorithm> #include <vector> #include <deque> #include <list> namespace providere_consulting { namespace iterators { class checked_container; class checked_iterator { friend class checked_container; public: checked_iterator() : prior(0), next(0), container(0) {} checked_iterator(const checked_iterator& other) : container(other.container) { if(other.is_valid()) { next = other.next; prior = &other; if(next != 0) { next->prior = this; } other.next = this; } else { next = 0; prior = 0; } } checked_iterator(const checked_container& container); ~checked_iterator() { if(is_valid()) { prior->next = next; if(next != 0) { next->prior = prior; } } } checked_iterator& operator=(checked_iterator other) { swap(other); return(*this); } bool is_valid() const { return(container != 0); } void swap(checked_iterator& other) { if(container != other.container) { std::swap(next, other.next); std::swap(prior, other.prior); set_other_pointers(); other.set_other_pointers(); } } void invalidate() const { if(next != 0) { next->prior = prior; } if(prior != 0) { prior->next = next; } container = 0; } private: static void invalidate_all(const checked_iterator* begin) { for(; begin != 0; begin = begin->next) { begin->container = 0; } } void set_other_pointers() { if(next != 0) { next->prior = this; } if(prior != 0) { prior->next = this; } } mutable const checked_iterator* next; mutable const checked_iterator* prior; mutable const checked_container* container; }; class checked_container { friend class checked_iterator; public: checked_container() : list() {} ~checked_container() { checked_iterator::invalidate_all(&list); } void invalidate_iterators() const { checked_iterator::invalidate_all(&list); } private: checked_iterator list; }; inline checked_iterator::checked_iterator(const checked_container& c) : container(&c) { next = container->list.next; prior = &container->list; set_other_pointers(); } template<class Iterator> class iterator_template; template<class Iterator> typename std::iterator_traits<Iterator>::difference_type operator-(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second); template<class Iterator> bool operator==(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second); template<class Iterator> bool operator<(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second); template<class Iterator> class iterator_template : public checked_iterator { typedef ::std::iterator_traits<Iterator> traits; template<class Iter> friend class iterator_template; public: typedef typename traits::value_type value_type; typedef typename traits::reference reference; typedef typename traits::pointer pointer; typedef typename traits::difference_type difference_type; typedef typename traits::iterator_category iterator_category; iterator_template() {} iterator_template(const Iterator& iter, const checked_container& container) : checked_iterator(container), impl(iter) {} //iterator_template(const iterator_template& other); template<class Iter> iterator_template(const iterator_template<Iter>& other) : checked_iterator(static_cast<const checked_iterator&>(other)), impl(other.impl) {} iterator_template& operator=(iterator_template other) { swap(other); return(*this); } ~iterator_template() { } reference operator*() { check_invariants(); return(*impl); } Iterator operator->() { check_invariants(); return(impl); } iterator_template& operator++() { check_invariants(); ++impl; return(*this); } iterator_template operator++(int) { iterator_template temp(*this); ++*this; return(temp); } iterator_template& operator--() { check_invariants(); --impl; return(*this); } iterator_template operator--(int) { iterator_template temp(*this); --*this; return(temp); } iterator_template& operator+=(difference_type difference) { check_invariants(); impl += difference; return(*this); } iterator_template& operator-=(difference_type difference) { check_invariants(); impl -= difference; return(*this); } friend typename traits::difference_type operator-<Iterator>(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second); friend bool operator== <>(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second); friend bool operator< <>(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second); void swap(iterator_template& other) { using std::swap; swap(impl, other.impl); checked_iterator::swap(static_cast<checked_iterator&>(other)); } Iterator get() { return(impl); } private: void check_invariants() const { assert(is_valid()); } Iterator impl; }; template<class Iterator> iterator_template<Iterator> operator+(iterator_template<Iterator> iter, typename std::iterator_traits<Iterator>::difference_type difference) { iter += difference; return(iter); } template<class Iterator> iterator_template<Iterator> operator+(typename std::iterator_traits<Iterator>::difference_type difference, iterator_template<Iterator> iter) { iter += difference; return(iter); } template<class Iterator> iterator_template<Iterator> operator-(iterator_template<Iterator> iter, typename std::iterator_traits<Iterator>::difference_type difference) { iter -= difference; return(iter); } template<class Iterator> typename std::iterator_traits<Iterator>::difference_type operator-(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second) { first.check_invariants(); second.check_invariants(); return(first.impl - second.impl); } template<class Iterator> bool operator==(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second) { first.check_invariants(); second.check_invariants(); return(first.impl == second.impl); } template<class Iterator> bool operator!=(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second) { return(!(first == second)); } template<class Iterator> bool operator<(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second) { first.check_invariants(); second.check_invariants(); return(first.impl < second.impl); } template<class Iterator> bool operator>(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second) { return(second < first); } template<class Iterator> bool operator<=(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second) { return(!(first > second)); } template<class Iterator> bool operator>=(const iterator_template<Iterator>& first, const iterator_template<Iterator>& second) { return(!(first < second)); } } template<class T, class Mutex> class locked_object; template<class T> struct locked_object_value { typedef T type; static void on_release(const T& t) {} }; template<class T> struct wrap_sequential_container : T, iterators::checked_container { typedef T base; typedef iterators::iterator_template<typename base::iterator> iterator; typedef iterators::iterator_template<typename base::const_iterator> const_iterator; typedef iterators::iterator_template<typename base::reverse_iterator> reverse_iterator; typedef iterators::iterator_template<typename base::const_reverse_iterator> const_reverse_iterator; using typename base::size_type; using typename base::const_reference; iterator begin() { iterator result(base::begin(), *this); return(result); } iterator end() { iterator result(base::end(), *this); return(result); } reverse_iterator rbegin() { reverse_iterator result(base::rbegin(), *this); return(result); } reverse_iterator rend() { reverse_iterator result(base::rend(), *this); return(result); } const_iterator begin() const { const_iterator result(base::begin(), *this); return(result); } const_iterator end() const { const_iterator result(base::end(), *this); return(result); } const_reverse_iterator rbegin() const { const_reverse_iterator result(base::rbegin(), *this); return(result); } const_reverse_iterator rend() const { const_reverse_iterator result(base::rend(), *this); return(result); } iterator insert(iterator pos, const_reference value) const { iterator result(base::insert(pos.get(), value), *this); return(result); } iterator insert(iterator pos, size_type size, const_reference value) const { iterator result(base::insert(pos.get(), size, value), *this); return(result); } template<class Iter> iterator insert(iterator pos, Iter begin, Iter end) const { iterator result(base::insert(pos.get(), begin, end), *this); return(result); } iterator erase(iterator pos) { iterator result(base::erase(pos.get()), *this); return(result); } iterator erase(iterator begin, iterator end) { iterator result(base::erase(begin.get(), end.get()), *this); return(result); } }; template<class T, class Allocator> struct locked_object_value<std::vector<T, Allocator> > { typedef wrap_sequential_container<std::vector<T, Allocator> > type; static void on_release(const type& t) { t.invalidate_iterators(); } }; template<class T, class Allocator> struct locked_object_value<std::deque<T, Allocator> > { typedef wrap_sequential_container<std::deque<T, Allocator> > type; static void on_release(const type& t) { t.invalidate_iterators(); } }; template<class T, class Allocator> struct locked_object_value<std::list<T, Allocator> > { struct type : wrap_sequential_container<std::list<T, Allocator> > { typedef wrap_sequential_container<std::list<T, Allocator> > base; void splice(typename base::iterator pos, std::list<T, Allocator>& other) { base::splice(pos.get(), other); } void splice(typename base::iterator pos, std::list<T, Allocator>& other, typename std::list<T, Allocator>::iterator begin) { base::splice(pos.get(), other, begin); } void splice(typename base::iterator pos, std::list<T, Allocator>& other, typename std::list<T, Allocator>::iterator begin, typename std::list<T, Allocator>::iterator end) { base::splice(pos.get(), other, begin, end); } }; static void on_release(const type& t) { t.invalidate_iterators(); } }; namespace scoped_lock_pointer_adl_barrier { template<class T> inline typename T::element_type& operator*(T& t) { return(*t.tptr); } template<class T, class Mutex> class scoped_lock_pointer { public: typedef T element_type; scoped_lock_pointer(locked_object<T, Mutex>& object) : tptr(&object.t), lock(object.mutex) {} ~scoped_lock_pointer() { locked_object_value<T>::on_release(*tptr); } template<class P> friend typename P::element_type& operator*(P&); T* operator->() { return(tptr); } private: scoped_lock_pointer(const scoped_lock_pointer&); scoped_lock_pointer& operator=(const scoped_lock_pointer&); typename locked_object_value<T>::type* tptr; typename Mutex::scoped_lock lock; }; template<class T, class Mutex> class const_scoped_lock_pointer { public: typedef const T element_type; const_scoped_lock_pointer(const locked_object<T, Mutex>& object) : tptr(&object.t), lock(object.mutex) {} ~const_scoped_lock_pointer() { locked_object_value<T>::on_release(*tptr); } template<class P> friend typename P::element_type& operator*(P&); const T* operator->() { return(tptr); } private: const_scoped_lock_pointer(const const_scoped_lock_pointer&); const_scoped_lock_pointer& operator=(const const_scoped_lock_pointer&); const typename locked_object_value<T>::type* tptr; typename Mutex::scoped_lock lock; }; } template<class T, class Mutex> class locked_object { public: friend class scoped_lock_pointer_adl_barrier::scoped_lock_pointer<T, Mutex>; typedef scoped_lock_pointer_adl_barrier::scoped_lock_pointer<T, Mutex> scoped_lock_pointer; friend class scoped_lock_pointer_adl_barrier::const_scoped_lock_pointer<T, Mutex>; typedef scoped_lock_pointer_adl_barrier::const_scoped_lock_pointer<T, Mutex> const_scoped_lock_pointer; locked_object() : t() {} locked_object(const T& arg) : t(t) {} template<class U> locked_object(U& u) : t(u) {} template<class U> locked_object(const U& u) : t(u) {} template<class U1, class U2> locked_object(U1& u1, U2& u2) : t(u1, u2) {} template<class U1, class U2> locked_object(const U1& u1, U2& u2) : t(u1, u2) {} template<class U1, class U2> locked_object(U1& u1, const U2& u2) : t(u1, u2) {} template<class U1, class U2> locked_object(const U1& u1, const U2& u2) : t(u1, u2) {} template<class U1, class U2, class U3> locked_object(U1& u1, U2& u2, U3& u3) : t(u1, u2) {} template<class U1, class U2, class U3> locked_object(const U1& u1, U2& u2, U3& u3) : t(u1, u2) {} template<class U1, class U2, class U3> locked_object(U1& u1, const U2& u2, U3& u3) : t(u1, u2) {} template<class U1, class U2, class U3> locked_object(U1& u1, U2& u2, const U3& u3) : t(u1, u2) {} template<class U1, class U2, class U3> locked_object(const U1& u1, const U2& u2, U3& u3) : t(u1, u2) {} template<class U1, class U2, class U3> locked_object(const U1& u1, U2& u2, const U3& u3) : t(u1, u2) {} template<class U1, class U2, class U3> locked_object(U1& u1, const U2& u2, const U3& u3) : t(u1, u2) {} template<class U1, class U2, class U3> locked_object(const U1& u1, const U2& u2, const U3& u3) : t(u1, u2) {} private: typename locked_object_value<T>::type t; mutable Mutex mutex; }; } #endif
participants (1)
-
Steven Watanabe