4 #include "boost/shared_ptr.hpp"
5 #include "glibmm/thread.h"
14 RCUManager (T* new_rcu_value) {
15 m_rcu_value = new boost::shared_ptr<T> (new_rcu_value);
18 virtual ~RCUManager() { delete m_rcu_value; }
20 boost::shared_ptr<T> reader () const { return *((boost::shared_ptr<T> *) g_atomic_pointer_get (&m_rcu_value)); }
22 virtual boost::shared_ptr<T> write_copy () = 0;
23 virtual bool update (boost::shared_ptr<T> new_value) = 0;
26 boost::shared_ptr<T>* m_rcu_value;
28 // this monstrosity is needed because of some wierd behavior by g++
30 gpointer * the_pointer() const { return (gpointer *) &m_rcu_value; }
35 class SerializedRCUManager : public RCUManager<T>
39 SerializedRCUManager(T* new_rcu_value)
40 : RCUManager<T>(new_rcu_value)
45 boost::shared_ptr<T> write_copy ()
49 // clean out any dead wood
51 typename std::list<boost::shared_ptr<T> >::iterator i;
53 for (i = m_dead_wood.begin(); i != m_dead_wood.end(); ) {
54 if ((*i).use_count() == 1) {
55 i = m_dead_wood.erase (i);
63 current_write_old = RCUManager<T>::m_rcu_value;
65 boost::shared_ptr<T> new_copy (new T(**current_write_old));
70 bool update (boost::shared_ptr<T> new_value)
72 // we hold the lock at this point effectively blocking
75 boost::shared_ptr<T>* new_spp = new boost::shared_ptr<T> (new_value);
77 // update, checking that nobody beat us to it
79 bool ret = g_atomic_pointer_compare_and_exchange (RCUManager<T>::the_pointer(),
80 (gpointer) current_write_old,
85 // successful update : put the old value into dead_wood,
87 m_dead_wood.push_back (*current_write_old);
89 // now delete it - this gets rid of the shared_ptr<T> but
90 // because dead_wood contains another shared_ptr<T> that
91 // references the same T, the underlying object lives on
93 delete current_write_old;
102 Glib::Mutex::Lock lm (m_lock);
103 m_dead_wood.clear ();
108 boost::shared_ptr<T>* current_write_old;
109 std::list<boost::shared_ptr<T> > m_dead_wood;
117 RCUWriter(RCUManager<T>& manager)
120 m_copy = m_manager.write_copy();
125 // we can check here that the refcount of m_copy is 1
127 if(m_copy.use_count() == 1) {
128 m_manager.update(m_copy);
136 // or operator boost::shared_ptr<T> ();
137 boost::shared_ptr<T> get_copy() { return m_copy; }
141 RCUManager<T>& m_manager;
143 // preferably this holds a pointer to T
144 boost::shared_ptr<T> m_copy;
147 #endif /* __pbd_rcu_h__ */