~ubuntu-branches/ubuntu/utopic/rlvm/utopic-proposed

« back to all changes in this revision

Viewing changes to src/base/observer_list.h

  • Committer: Bazaar Package Importer
  • Author(s): Ying-Chun Liu (PaulLiu), Ying-Chun Liu (PaulLiu), Elliot Glaysher
  • Date: 2011-05-19 00:28:44 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20110519002844-qszwmj7oiixww0eg
Tags: 0.12-1
[ Ying-Chun Liu (PaulLiu) <paulliu@debian.org> ]
* New upstream release

[ Elliot Glaysher <glaysher@umich.edu> ]
* New GTK+ interface with desktop integration and UI refinements
* Partial Japanese localizations
* Fix graphics corruption in in-game dialogs when a dialog is brought
  up, and then fullscreen mode activated
* Smooth the output of text in rlBabel using games
* Don't play voice samples while fast forwarding

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
 
2
// Use of this source code is governed by a BSD-style license that can be
 
3
// found in the LICENSE file.
 
4
 
 
5
#ifndef BASE_OBSERVER_LIST_H__
 
6
#define BASE_OBSERVER_LIST_H__
 
7
#pragma once
 
8
 
 
9
#include <algorithm>
 
10
#include <limits>
 
11
#include <vector>
 
12
 
 
13
///////////////////////////////////////////////////////////////////////////////
 
14
//
 
15
// OVERVIEW:
 
16
//
 
17
//   A container for a list of observers.  Unlike a normal STL vector or list,
 
18
//   this container can be modified during iteration without invalidating the
 
19
//   iterator.  So, it safely handles the case of an observer removing itself
 
20
//   or other observers from the list while observers are being notified.
 
21
//
 
22
// TYPICAL USAGE:
 
23
//
 
24
//   class MyWidget {
 
25
//    public:
 
26
//     ...
 
27
//
 
28
//     class Observer {
 
29
//      public:
 
30
//       virtual void OnFoo(MyWidget* w) = 0;
 
31
//       virtual void OnBar(MyWidget* w, int x, int y) = 0;
 
32
//     };
 
33
//
 
34
//     void AddObserver(Observer* obs) {
 
35
//       observer_list_.AddObserver(obs);
 
36
//     }
 
37
//
 
38
//     void RemoveObserver(Observer* obs) {
 
39
//       observer_list_.RemoveObserver(obs);
 
40
//     }
 
41
//
 
42
//     void NotifyFoo() {
 
43
//       FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this));
 
44
//     }
 
45
//
 
46
//     void NotifyBar(int x, int y) {
 
47
//       FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y));
 
48
//     }
 
49
//
 
50
//    private:
 
51
//     ObserverList<Observer> observer_list_;
 
52
//   };
 
53
//
 
54
//
 
55
///////////////////////////////////////////////////////////////////////////////
 
56
 
 
57
template <typename ObserverType>
 
58
class ObserverListThreadSafe;
 
59
 
 
60
template <class ObserverType>
 
61
class ObserverListBase {
 
62
 public:
 
63
  // Enumeration of which observers are notified.
 
64
  enum NotificationType {
 
65
    // Specifies that any observers added during notification are notified.
 
66
    // This is the default type if non type is provided to the constructor.
 
67
    NOTIFY_ALL,
 
68
 
 
69
    // Specifies that observers added while sending out notification are not
 
70
    // notified.
 
71
    NOTIFY_EXISTING_ONLY
 
72
  };
 
73
 
 
74
  // An iterator class that can be used to access the list of observers.  See
 
75
  // also the FOR_EACH_OBSERVER macro defined below.
 
76
  class Iterator {
 
77
   public:
 
78
    Iterator(ObserverListBase<ObserverType>& list)
 
79
        : list_(list),
 
80
          index_(0),
 
81
          max_index_(list.type_ == NOTIFY_ALL ?
 
82
                     std::numeric_limits<size_t>::max() :
 
83
                     list.observers_.size()) {
 
84
      ++list_.notify_depth_;
 
85
    }
 
86
 
 
87
    ~Iterator() {
 
88
      if (--list_.notify_depth_ == 0)
 
89
        list_.Compact();
 
90
    }
 
91
 
 
92
    ObserverType* GetNext() {
 
93
      ListType& observers = list_.observers_;
 
94
      // Advance if the current element is null
 
95
      size_t max_index = std::min(max_index_, observers.size());
 
96
      while (index_ < max_index && !observers[index_])
 
97
        ++index_;
 
98
      return index_ < max_index ? observers[index_++] : NULL;
 
99
    }
 
100
 
 
101
   private:
 
102
    ObserverListBase<ObserverType>& list_;
 
103
    size_t index_;
 
104
    size_t max_index_;
 
105
  };
 
106
 
 
107
  ObserverListBase() : notify_depth_(0), type_(NOTIFY_ALL) {}
 
108
  explicit ObserverListBase(NotificationType type)
 
109
      : notify_depth_(0), type_(type) {}
 
110
 
 
111
  // Add an observer to the list.
 
112
  void AddObserver(ObserverType* obs) {
 
113
    observers_.push_back(obs);
 
114
  }
 
115
 
 
116
  // Remove an observer from the list.
 
117
  void RemoveObserver(ObserverType* obs) {
 
118
    typename ListType::iterator it =
 
119
      std::find(observers_.begin(), observers_.end(), obs);
 
120
    if (it != observers_.end()) {
 
121
      if (notify_depth_) {
 
122
        *it = 0;
 
123
      } else {
 
124
        observers_.erase(it);
 
125
      }
 
126
    }
 
127
  }
 
128
 
 
129
  bool HasObserver(ObserverType* observer) const {
 
130
    for (size_t i = 0; i < observers_.size(); ++i) {
 
131
      if (observers_[i] == observer)
 
132
        return true;
 
133
    }
 
134
    return false;
 
135
  }
 
136
 
 
137
  void Clear() {
 
138
    if (notify_depth_) {
 
139
      for (typename ListType::iterator it = observers_.begin();
 
140
           it != observers_.end(); ++it) {
 
141
        *it = 0;
 
142
      }
 
143
    } else {
 
144
      observers_.clear();
 
145
    }
 
146
  }
 
147
 
 
148
  size_t size() const { return observers_.size(); }
 
149
 
 
150
 protected:
 
151
  void Compact() {
 
152
    typename ListType::iterator it = observers_.begin();
 
153
    while (it != observers_.end()) {
 
154
      if (*it) {
 
155
        ++it;
 
156
      } else {
 
157
        it = observers_.erase(it);
 
158
      }
 
159
    }
 
160
  }
 
161
 
 
162
 private:
 
163
  friend class ObserverListThreadSafe<ObserverType>;
 
164
 
 
165
  typedef std::vector<ObserverType*> ListType;
 
166
 
 
167
  ListType observers_;
 
168
  int notify_depth_;
 
169
  NotificationType type_;
 
170
 
 
171
  friend class ObserverListBase::Iterator;
 
172
};
 
173
 
 
174
template <class ObserverType, bool check_empty = false>
 
175
class ObserverList : public ObserverListBase<ObserverType> {
 
176
 public:
 
177
  typedef typename ObserverListBase<ObserverType>::NotificationType
 
178
      NotificationType;
 
179
 
 
180
  ObserverList() {}
 
181
  explicit ObserverList(NotificationType type)
 
182
      : ObserverListBase<ObserverType>(type) {}
 
183
 
 
184
  ~ObserverList() {
 
185
    // When check_empty is true, assert that the list is empty on destruction.
 
186
    if (check_empty) {
 
187
      ObserverListBase<ObserverType>::Compact();
 
188
    }
 
189
  }
 
190
};
 
191
 
 
192
#define FOR_EACH_OBSERVER(ObserverType, observer_list, func)  \
 
193
  do {                                                        \
 
194
    ObserverListBase<ObserverType>::Iterator it(observer_list);   \
 
195
    ObserverType* obs;                                        \
 
196
    while ((obs = it.GetNext()) != NULL)                      \
 
197
      obs->func;                                              \
 
198
  } while (0)
 
199
 
 
200
#endif  // BASE_OBSERVER_LIST_H__