|
Boost : |
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2007-08-25 21:30:39
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk