Class template monitor_ptr

poet::monitor_ptr — A smart pointer which provides automatically locked access to an object.

Synopsis

template<typename T, typename Mutex = boost::mutex> 
class monitor_ptr {
public:
  // types
  typedef T     element_type;
  typedef Mutex mutex_type;  

  // construct/copy/destruct
  monitor_ptr();
  template<typename U> explicit monitor_ptr(U*);
  monitor_ptr(boost::shared_ptr<T>);
  monitor_ptr(const monitor_ptr &);
  template<typename U> monitor_ptr(const monitor_ptr<U, Mutex> &);
  template<typename U> monitor_ptr(const monitor_ptr<U, Mutex> &, T*);
  monitor_ptr& operator=(const monitor_ptr &);
  virtual ~monitor_ptr();

  // public member functions
  const boost::shared_ptr<T> & direct() const;
  monitor_unique_lock<const monitor_ptr> operator->() const;
   operator bool() const;
  template<typename U> void reset(U*);
  void reset(const boost::shared_ptr<T> &);
  void reset();
  template<typename U> void reset(const monitor_ptr<U, Mutex> &, T*);
  void swap(monitor_ptr &);

  // Boost.Thread Lockable concept support
  void lock() const;
  bool try_lock() const;
  void unlock() const;

  // Boost.Thread TimedLockable concept support
  template<typename Timeout> bool timed_lock(const Timeout &) const;

  // Boost.Thread SharedLockable concept support
  void lock_shared() const;
  bool try_lock_shared() const;
  template<typename Timeout> bool timed_lock_shared(const Timeout &) const;
  void unlock_shared() const;
  void unlock_and_lock_shared() const;

  // Boost.Thread UpgradeLockable concept support
  void lock_upgrade() const;
  void unlock_upgrade() const;
  void unlock_upgrade_and_lock() const;
  void unlock_upgrade_and_lock_shared() const;
  void unlock_and_lock_upgrade() const;
};

// free functions: casts
template<typename T, typename U, typename Mutex> 
  monitor_ptr<T, Mutex> static_pointer_cast(const monitor_ptr<U, Mutex> &);
template<typename T, typename U, typename Mutex> 
  monitor_ptr<T, Mutex> dynamic_pointer_cast(const monitor_ptr<U, Mutex> &);
template<typename T, typename U, typename Mutex> 
  monitor_ptr<T, Mutex> const_pointer_cast(const monitor_ptr<U, Mutex> &);

// free functions: comparison
template<typename T, typename MutexA, typename U, typename MutexB> 
  bool operator==(const monitor_ptr<T, MutexT> &, 
                  const monitor_ptr<U, MutexU> &);
template<typename T, typename MutexA, typename U, typename MutexB> 
  bool operator!=(const monitor_ptr<T, MutexT> &, 
                  const monitor_ptr<U, MutexU> &);
template<typename T, typename MutexA, typename U, typename MutexB> 
  bool operator<(const monitor_ptr<T, MutexT> &, 
                 const monitor_ptr<U, MutexU> &);

// free function: swap
template<typename T, typename Mutex> 
  void swap(monitor_ptr<T, Mutex> &, monitor_ptr<T, Mutex> &);

Description

monitor_ptr allows for the easy creation of monitor objects. A monitor_ptr provides automatically locked access to an object's members when they are accessed through the overloaded operator->, or alternatively through one of the lock classes from poet/monitor_locks.hpp. It is based in part on ideas taken from "Wrapping C++ Member Function Calls" by Bjarne Stroustroup and "Monitor Object: An Object Behavioral Pattern for Concurrent Programming" by Douglas C. Schmidt.

Although any object may be passed to a monitor_ptr, special support is provided for classes derived from monitor_base. This allows classes derived from monitor_base to wait on conditions inside member function calls, releasing the monitor_ptr's mutex until the condition is met.

The Mutex template type parameter must model the Lockable concept from the Boost.Thread library. The monitor_ptr itself models the Lockable concept, and will also model any of the TimedLockable, SharedLockable, or UpgradeLockable concepts if the underlying Mutex template type supports them. Note however, a monitor_ptr must not be empty when being used as a mutex. An empty monitor_ptr will throw a boost::lock_error if any attempt is made to use lock, unlock, or any other part of the monitor_ptr interface which models the Boost.Thread concepts.

The interfaces defined by the Boost.Thread mutex concepts should generally not be used directly by the user. They are intended to be used by scoped lock classes such as monitor_unique_lock, which provide a safer means to perform locking. See the "Mutex Concepts" documentation in the Boost.Thread library for more information about the Lockable, etc. concepts.

Note that while monitor_ptr provides thread-safe access to the object it is pointing at, it does not provide a strong thread-safety guarantee for itself. That is, a single monitor_ptr object should not be modified concurrently by multiple threads. Rather, each thread should be passed its own copy of the monitor_ptr to use. The thread-safety guarantees of monitor_ptr are similar to those provided by boost::shared_ptr.

Example Code

See also

  • monitor: an alternative to the monitor_ptr class, which stores its wrapped object by value instead of acting like a pointer.

monitor_ptr public construct/copy/destruct

  1. monitor_ptr();

    The default constructor creates an empty monitor_ptr.

  2. template<typename U> explicit monitor_ptr(U* pointer);

    Creates a monitor_ptr which wraps the specified pointer. The monitor_ptr internally stores pointer in a boost::shared_ptr. Thus the pointer will be automatically deleted when the last copy of this monitor_ptr is destroyed.

  3. monitor_ptr(boost::shared_ptr<T> smart_pointer);

    Creates a monitor_ptr which wraps the specified pointer. This constructor allows the monitor_ptr to be initialized with a boost::shared_ptr that has a custom deleter.

  4. monitor_ptr(const monitor_ptr & other);

    The copy constructor creates a monitor_ptr which shares the same pointer, mutex, and condition as the original.

  5. template<typename U> monitor_ptr(const monitor_ptr<U, Mutex> & other);

    This constructor creates a monitor_ptr which shares the same pointer (implicitly converted), mutex, and condition as the original.

  6. template<typename U> 
      monitor_ptr(const monitor_ptr<U, Mutex> & other, T* pointer);

    This is an aliasing constructor, similar in function to the aliasing constructor of shared_ptr. It creates a monitor_ptr which shares ownership and uses the same mutex as other, but which points at the object specified by pointer when dereferenced. The types T and U may be unrelated. It is useful for creating monitor_ptrs to objects which are only indirectly owned by a monitor_ptr, for example:

    struct coordinates
    {
    	int x;
    	int y;
    };
    
    // ...
    
    poet::monitor_ptr<coordinates> coords(new coordinates());
    // x_mon shares ownership of coords object, but points at coords->x.
    // x_mon might be needed to pass the x member of the coords object to a function
    // expecting an argument of type poet::monitor_ptr<int>.
    poet::monitor_ptr<int> x_mon(coords, &coords->x);
    // the following block has the same effect as "coords->x = 5;"
    {
    	poet::monitor_unique_lock<monitor_ptr<int> > x_lock(x_mon);
    	*x_lock = 5;
    }

  7. monitor_ptr& operator=(const monitor_ptr & rhs);

    After assignment, the two monitor_ptrs will share the same pointer, mutex, and condition variable.

  8. virtual ~monitor_ptr();

    A monitor_ptr and all its copies share ownership of an underlying pointer, mutex, and condition variable. The pointer, mutex, and condition are deleted when the last copy of the monitor_ptr is destroyed. The deleter for the underlying pointer may be customized by using the constructor which takes a boost::shared_ptr as its parameter.

monitor_ptr public member functions

  1. const boost::shared_ptr<T> & direct() const;

    Gives direct unlocked access to the underlying pointer.

  2. monitor_unique_lock<const monitor_ptr> operator->() const;

    Returns a temporary monitor_unique_lock which locks the monitor_ptr's mutex. The operator->() of the returned monitor_unique_lock object will be automatically called in turn (overloading operator->() is special in that way), which will utimately result in a call of operator->() on the monitor_ptr's underlying pointer. The mutex is automatically unlocked after the member access completes by the monitor_unique_lock destructor.

    If more flexibility is desired, the lock types from poet/monitor_locks.hpp provide alternatives to monitor_ptr::operator->.

  3.  operator bool() const;

    Conversion to bool results in false if the monitor_ptr's underlying pointer is null, true otherwise.

  4. template<typename U> void reset(U* pointer);
    void reset(const boost::shared_ptr<T> & smart_pointer);
    void reset();
    template<typename U> 
      void reset(const monitor_ptr<U, Mutex> & other, T* pointer);

    Resets the monitor_ptr's underlying pointer using the specified parameter(s). A new mutex and condition are also created (except in the no-parameter case, where they are simply deleted).

    The overload which takes a monitor_ptr and T* argument makes *this into an aliased monitor_ptr, which shares ownership and its mutex with other, but which points at the address given by pointer. See the description of the aliasing constructor for more information.

  5. void swap(monitor_ptr & other);

    Swaps *this and other.

monitor_ptr Boost.Thread Lockable concept support

  1. void lock() const;
  2. bool try_lock() const;
  3. void unlock() const;

monitor_ptr Boost.Thread TimedLockable concept support

  1. template<typename Timeout> bool timed_lock(const Timeout & t) const;

monitor_ptr Boost.Thread SharedLockable concept support

  1. void lock_shared() const;
  2. bool try_lock_shared() const;
  3. template<typename Timeout> bool timed_lock_shared(const Timeout & t) const;
  4. void unlock_shared() const;
  5. void unlock_and_lock_shared() const;

monitor_ptr Boost.Thread UpgradeLockable concept support

  1. void lock_upgrade() const;
  2. void unlock_upgrade() const;
  3. void unlock_upgrade_and_lock() const;
  4. void unlock_upgrade_and_lock_shared() const;
  5. void unlock_and_lock_upgrade() const;

monitor_ptr free functions: casts

  1. template<typename T, typename U, typename Mutex> 
      monitor_ptr<T, Mutex> static_pointer_cast(const monitor_ptr<U, Mutex> & p);

    Casts a monitor_ptr by applying boost::static_pointer_cast<U> to the monitor_ptr's underlying shared_ptr.

  2. template<typename T, typename U, typename Mutex> 
      monitor_ptr<T, Mutex> dynamic_pointer_cast(const monitor_ptr<U, Mutex> & p);

    Casts a monitor_ptr by applying boost::dynamic_pointer_cast<U> to the monitor_ptr's underlying shared_ptr.

  3. template<typename T, typename U, typename Mutex> 
      monitor_ptr<T, Mutex> const_pointer_cast(const monitor_ptr<U, Mutex> & p);

    Casts a monitor_ptr by applying boost::const_pointer_cast<U> to the monitor_ptr's underlying shared_ptr.

monitor_ptr free functions: comparison

  1. template<typename T, typename MutexA, typename U, typename MutexB> 
      bool operator==(const monitor_ptr<T, MutexT> & a, 
                      const monitor_ptr<U, MutexU> & b);

    Returns:

    Returns the result of applying operator== to the underlying shared_ptrs of the two monitor_ptr arguments.

  2. template<typename T, typename MutexA, typename U, typename MutexB> 
      bool operator!=(const monitor_ptr<T, MutexT> & a, 
                      const monitor_ptr<U, MutexU> & b);

    Returns:

    Returns the result of applying operator!= to the underlying shared_ptrs of the two monitor_ptr arguments.

  3. template<typename T, typename MutexA, typename U, typename MutexB> 
      bool operator<(const monitor_ptr<T, MutexT> & a, 
                     const monitor_ptr<U, MutexU> & b);

    Returns:

    Returns the result of applying operator< to the underlying shared_ptrs of the two monitor_ptr arguments.

monitor_ptr free function: swap

  1. template<typename T, typename Mutex> 
      void swap(monitor_ptr<T, Mutex> & monitor0, 
                monitor_ptr<T, Mutex> & monitor1);

    Swaps monitor0 and monitor1. This function is provided to enhance efficiency with generic algorithms.