Continued refactoring.
[tagua/yd.git] / src / weakset.h
blob62dc35517a55ef420476998694852061999ddb2b
1 /*
2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 */
11 #ifndef WEAK_SET
12 #define WEAK_SET
14 #include <boost/weak_ptr.hpp>
15 #include <list>
17 #ifdef WEAK_SET_DEBUG
18 #include <iostream>
19 using namespace std;
20 #endif // WEAK_SET_DEBUG
22 /**
23 * @brief An implementation of a set of weak references.
25 * weak_set is a set of weak_pointers which are automatically collected
26 * and removed when the pointed object is destroyed.
28 template <typename T>
29 class weak_set {
30 typedef std::list<boost::weak_ptr<T> > inner_set;
31 typedef typename inner_set::iterator inner_iterator;
32 friend class iterator;
33 mutable inner_set m_set;
34 public:
35 class iterator {
36 friend class weak_set<T>;
37 mutable inner_iterator m_it;
38 boost::shared_ptr<T> obj; // this prevents the stored object from being collected
39 weak_set<T>& m_parent;
41 iterator(const inner_iterator& it, weak_set<T>& parent)
42 : m_it(it)
43 , m_parent(parent) {
44 skip_garbage();
47 void skip_garbage() {
48 #ifdef WEAK_SET_DEBUG
49 cout << "skipping garbage" << endl;
50 uint c = 0;
51 #endif // WEAK_SET_DEBUG
52 while (true) {
53 if (m_it == m_parent.m_set.end()) break;
54 boost::weak_ptr<T> wp = *m_it;
55 if (obj = wp.lock()) break;
57 // while (m_it != m_parent.m_set.end() && !(obj = (*m_it).lock())) {
58 #ifdef WEAK_SET_DEBUG
59 cout << "iteration " << c++ << endl;
60 #endif // WEAK_SET_DEBUG
62 // the current reference is dangling:
63 // remove it from the list and get the next one
64 #ifdef WEAK_SET_DEBUG
65 cout << "dangling reference! removing it" << endl;
66 #endif // WEAK_SET_DEBUG
67 m_it = m_parent.m_set.erase(m_it);
69 // at this point either
70 // m_it < m_parent.m_set.end() _and_ obj is a valid shared_ptr
71 // or
72 // m_it == m_parent.m_set.end()
73 #ifdef WEAK_SET_DEBUG
74 if (obj)
75 cout << "no iteration done: uses = " << obj.use_count() << ", obj = " << *obj << endl;
76 else
77 cout << "we're at the end" << endl;
78 #endif // WEAK_SET_DEBUG
80 public:
81 /**
82 * Check two iterators for equality.
84 bool operator==(const iterator& other) { return m_it == other.m_it; }
86 /**
87 * Equivalent to !operator==.
89 bool operator!=(const iterator& other) { return !operator==(other); }
91 /**
92 * Pre-increment operator. Modifity the iterator so
93 * that it points to the next valid object.
94 * @return The incremented iterator.
96 iterator& operator++() {
97 #ifdef WEAK_SET_DEBUG
98 cout << "incrementing" << endl;
99 #endif // WEAK_SET_DEBUG
100 ++m_it;
101 obj.reset();
102 skip_garbage();
103 #ifdef WEAK_SET_DEBUG
104 cout << "done incrementing" << endl;
105 #endif // WEAK_SET_DEBUG
106 return *this;
110 * Post-increment operator. Modifity the iterator so
111 * that it points to the next valid object.
112 * @return The iterator before being incremented.
114 // iterator operator++(int) { return iterator(m_it++, m_parent); }
117 * @return a pointer to the stored object.
118 * @note This function is guaranteed to return a valid
119 * non-null pointer if the iterator is valid
120 * and less than the past-the-end iterator.
122 T* get() { return obj.get(); }
125 * @return a pointer to the stored object.
126 * @sa get
128 T* operator->() { return get(); }
131 * @return a reference to the stored object.
132 * @sa get
134 T& operator*() { return *get(); }
138 * Add an object to the container.
139 * @return an iterator referring to the newly inserted object.
140 * @note No iterator is invalidated by an insert operation.
142 iterator insert(const boost::shared_ptr<T>& x) {
143 return iterator(m_set.insert(m_set.end(), x), *this);
147 * @return an iterator pointing to the first element of
148 * the container, which can be used for iterating.
150 iterator begin() {
151 return iterator(m_set.begin(), *this);
155 * @return a past-the-end iterator.
157 iterator end() {
158 return iterator(m_set.end(), *this);
162 #endif // WEAK_SET