From caf0739b59c6191a04dda0074b186ff94eae9c0a Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 27 Jul 2006 16:58:20 +0000 Subject: [PATCH] add forgotten rcu.h header git-svn-id: svn://localhost/ardour2/trunk@708 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/pbd/pbd/rcu.h | 120 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 libs/pbd/pbd/rcu.h diff --git a/libs/pbd/pbd/rcu.h b/libs/pbd/pbd/rcu.h new file mode 100644 index 0000000000..6d9586cb3c --- /dev/null +++ b/libs/pbd/pbd/rcu.h @@ -0,0 +1,120 @@ +#ifndef __pbd_rcu_h__ +#define __pbd_rcu_h__ + +#include "boost/shared_ptr.hpp" +#include "glibmm/thread.h" + +#include + +template +class RCUManager +{ +public: + + RCUManager (T* new_rcu_value) + : m_rcu_value(new_rcu_value) + { + + } + + virtual ~RCUManager() { } + + boost::shared_ptr reader () const { return m_rcu_value; } + + // should be private + virtual boost::shared_ptr write_copy () = 0; + + // should be private + virtual void update (boost::shared_ptr new_value) = 0; + +protected: + + boost::shared_ptr m_rcu_value; + + +}; + + +template +class SerializedRCUManager : public RCUManager +{ +public: + + SerializedRCUManager(T* new_rcu_value) + : RCUManager(new_rcu_value) + { + + } + + virtual boost::shared_ptr write_copy () + { + m_lock.lock(); + + // I hope this is doing what I think it is doing :) + boost::shared_ptr new_copy(new T(*RCUManager::m_rcu_value)); + + // XXX todo remove old copies with only 1 reference from the list. + + return new_copy; + } + + virtual void update (boost::shared_ptr new_value) + { + // So a current reader doesn't hold the only reference to + // the existing value when we assign it a new value which + // should ensure that deletion of old values doesn't + // occur in a reader thread. + boost::shared_ptr old_copy = RCUManager::m_rcu_value; + + // we hold the lock at this point effectively blocking + // other writers. + RCUManager::m_rcu_value = new_value; + + + // XXX add the old value to the list of old copies. + + m_lock.unlock(); + } + +private: + Glib::Mutex m_lock; + + std::list > m_old_values; +}; + +template +class RCUWriter +{ +public: + + RCUWriter(RCUManager& manager) + : m_manager(manager) + { + m_copy = m_manager.write_copy(); + } + + ~RCUWriter() + { + // we can check here that the refcount of m_copy is 1 + + if(m_copy.use_count() == 1) { + m_manager.update(m_copy); + } else { + + // critical error. + } + + } + + // or operator boost::shared_ptr (); + boost::shared_ptr get_copy() { return m_copy; } + +private: + + RCUManager& m_manager; + + // preferably this holds a pointer to T + boost::shared_ptr m_copy; +}; + +#endif /* __pbd_rcu_h__ */