4 #include "boost/shared_ptr.hpp"
5 #include "glibmm/thread.h"
14 RCUManager (T* new_rcu_value) {
15 x.m_rcu_value = new boost::shared_ptr<T> (new_rcu_value);
18 virtual ~RCUManager() { delete x.m_rcu_value; }
20 boost::shared_ptr<T> reader () const { return *((boost::shared_ptr<T> *) g_atomic_pointer_get (&x.gptr)); }
22 virtual boost::shared_ptr<T> write_copy () = 0;
23 virtual bool update (boost::shared_ptr<T> new_value) = 0;
27 boost::shared_ptr<T>* m_rcu_value;
28 volatile gpointer gptr;
34 class SerializedRCUManager : public RCUManager<T>
38 SerializedRCUManager(T* new_rcu_value)
39 : RCUManager<T>(new_rcu_value)
44 boost::shared_ptr<T> write_copy ()
48 // clean out any dead wood
50 typename std::list<boost::shared_ptr<T> >::iterator i;
52 for (i = m_dead_wood.begin(); i != m_dead_wood.end(); ) {
53 if ((*i).use_count() == 1) {
54 i = m_dead_wood.erase (i);
62 current_write_old = RCUManager<T>::x.m_rcu_value;
64 boost::shared_ptr<T> new_copy (new T(**current_write_old));
69 bool update (boost::shared_ptr<T> new_value)
71 // we hold the lock at this point effectively blocking
74 boost::shared_ptr<T>* new_spp = new boost::shared_ptr<T> (new_value);
76 // update, checking that nobody beat us to it
78 bool ret = g_atomic_pointer_compare_and_exchange (&RCUManager<T>::x.gptr,
79 (gpointer) current_write_old,
84 // successful update : put the old value into dead_wood,
86 m_dead_wood.push_back (*current_write_old);
88 // now delete it - this gets rid of the shared_ptr<T> but
89 // because dead_wood contains another shared_ptr<T> that
90 // references the same T, the underlying object lives on
92 delete current_write_old;
101 Glib::Mutex::Lock lm (m_lock);
102 m_dead_wood.clear ();
107 boost::shared_ptr<T>* current_write_old;
108 std::list<boost::shared_ptr<T> > m_dead_wood;
116 RCUWriter(RCUManager<T>& manager)
119 m_copy = m_manager.write_copy();
124 // we can check here that the refcount of m_copy is 1
126 if(m_copy.use_count() == 1) {
127 m_manager.update(m_copy);
135 // or operator boost::shared_ptr<T> ();
136 boost::shared_ptr<T> get_copy() { return m_copy; }
140 RCUManager<T>& m_manager;
142 // preferably this holds a pointer to T
143 boost::shared_ptr<T> m_copy;
146 #endif /* __pbd_rcu_h__ */