4 #include "boost/shared_ptr.hpp"
5 #include "glibmm/thread.h"
15 RCUManager (T* new_rcu_value) {
16 m_rcu_value = new boost::shared_ptr<T> (new_rcu_value);
19 virtual ~RCUManager() { delete m_rcu_value; }
21 boost::shared_ptr<T> reader () const { return *((boost::shared_ptr<T> *) g_atomic_pointer_get (&m_rcu_value)); }
23 virtual boost::shared_ptr<T> write_copy () = 0;
24 virtual bool update (boost::shared_ptr<T> new_value) = 0;
27 boost::shared_ptr<T>* m_rcu_value;
29 // this monstrosity is needed because of some wierd behavior by g++
31 gpointer * the_pointer() const { return (gpointer *) &m_rcu_value; }
36 class SerializedRCUManager : public RCUManager<T>
40 SerializedRCUManager(T* new_rcu_value)
41 : RCUManager<T>(new_rcu_value)
46 virtual boost::shared_ptr<T> write_copy ()
50 // clean out any dead wood
52 typename std::list<boost::shared_ptr<T> >::iterator i;
54 for (i = m_dead_wood.begin(); i != m_dead_wood.end(); ) {
55 if ((*i).use_count() == 1) {
56 i = m_dead_wood.erase (i);
64 current_write_old = RCUManager<T>::m_rcu_value;
66 boost::shared_ptr<T> new_copy (new T(**current_write_old));
71 virtual bool update (boost::shared_ptr<T> new_value)
73 // we hold the lock at this point effectively blocking
76 boost::shared_ptr<T>* new_spp = new boost::shared_ptr<T> (new_value);
78 // update, checking that nobody beat us to it
80 bool ret = g_atomic_pointer_compare_and_exchange (RCUManager<T>::the_pointer(),
81 (gpointer) current_write_old,
86 // successful update : put the old value into dead_wood,
88 m_dead_wood.push_back (*current_write_old);
90 // now delete it - this gets rid of the shared_ptr<T> but
91 // because dead_wood contains another shared_ptr<T> that
92 // references the same T, the underlying object lives on
94 delete current_write_old;
104 boost::shared_ptr<T>* current_write_old;
105 std::list<boost::shared_ptr<T> > m_dead_wood;
113 RCUWriter(RCUManager<T>& manager)
116 m_copy = m_manager.write_copy();
121 // we can check here that the refcount of m_copy is 1
123 if(m_copy.use_count() == 1) {
124 m_manager.update(m_copy);
132 // or operator boost::shared_ptr<T> ();
133 boost::shared_ptr<T> get_copy() { return m_copy; }
137 RCUManager<T>& m_manager;
139 // preferably this holds a pointer to T
140 boost::shared_ptr<T> m_copy;
143 #endif /* __pbd_rcu_h__ */