// Copyright (c) 2009 João Abecasis // // 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 SAGA_ADAPTORS_CONDOR_JOB_SYNCHRONIZED_HPP_INCLUDED_ #define SAGA_ADAPTORS_CONDOR_JOB_SYNCHRONIZED_HPP_INCLUDED_ #include #include #include #include namespace saga { namespace adaptors { namespace condor { namespace detail { template struct synchronized_base : boost::noncopyable { struct lock_base { lock_base(synchronized_base const & sb) : p_(boost::addressof(sb)) { #if BOOST_VERSION >= 103500 p_->lock_.lock(); #else // HACK: This version is specific to Boost.Thread mutexes. // If need comes, locking/unlocking should be moved to an // external utility and generalized... boost::detail::thread::lock_ops ::lock(p_->lock_); #endif } // Move constructor lock_base(lock_base const & that) : p_(0) { *this = that; } ~lock_base() { if (p_) { #if BOOST_VERSION >= 103500 p_->lock_.unlock(); #else // HACK: This version is specific to Boost.Thread mutexes. // If need comes, locking/unlocking should be moved to an // external utility and generalized... boost::detail::thread::lock_ops ::unlock(p_->lock_); #endif } } // Move assignment lock_base & operator=(lock_base const & that) { BOOST_ASSERT(!p_ && "Moving to initialized lock_base not supported."); std::swap(p_, that.p_); return *this; } void release() { lock_base that = *this; } protected: // Type is movable, hence the mutable qualification mutable synchronized_base const * p_; }; private: // Also locked on const accesses mutable Lockable lock_; }; } // namespace detail template struct synchronized : detail::synchronized_base { private: typedef detail::synchronized_base base; public: synchronized() {} // TODO: More forwarding constructors... template synchronized(U const &u) : value_(u) { } // lock and const_lock are supposed to be short-lived temporaries, // although this is not a requirement. // // These classes have move-on-copy semantics and should be handled with // care, for that reason. struct const_lock : base::lock_base { typedef typename base::lock_base base; const_lock(synchronized const & sync) : base(sync) {} T const * operator->() const { return boost::addressof(get()); } T const & get() const { BOOST_ASSERT(base::p_ && "Using uninitialized lock!"); return static_cast(base::p_)->value_; } }; struct lock : const_lock { lock(synchronized & sync) : const_lock(sync) {} T * operator->() const { return boost::addressof(get()); } T & get() const { return const_cast(const_lock::get()); } }; lock operator->() { return lock(*this); } const_lock operator->() const { return const_lock(*this); } private: T value_; }; }}} // namespace saga::adaptors::condor #endif // include guard