KiCad PCB EDA Suite
observable.cpp
Go to the documentation of this file.
1/*
2* This program source code file is part of KICAD, a free EDA CAD application.
3*
4* Copyright (C) 2016 Kicad Developers, see change_log.txt for contributors.
5*
6* This program is free software; you can redistribute it and/or
7* modify it under the terms of the GNU General Public License
8* as published by the Free Software Foundation; either version 2
9* of the License, or (at your option) any later version.
10*
11* This program is distributed in the hope that it will be useful,
12* but WITHOUT ANY WARRANTY; without even the implied warranty of
13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14* GNU General Public License for more details.
15*
16* You should have received a copy of the GNU General Public License
17* along with this program; if not, you may find one here:
18* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19* or you may search the http://www.gnu.org website for the version 2 license,
20* or you may write to the Free Software Foundation, Inc.,
21* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22*/
23
24#include "observable.h"
25#include <algorithm>
26
27namespace UTIL {
28
29 namespace DETAIL {
30
31 template<typename T>
32 struct equals {
33 equals( const T& val ) : val_( val ) {}
34
35 bool operator()( const T& val ) const
36 {
37 return val == val_;
38 }
39
40 private:
41 const T& val_;
42 };
43
44
46 : iteration_count_( 0 ), owned_by_( owned_by )
47 {}
48
49
51 {
52 return owned_by_ == nullptr;
53 }
54
55
57 {
58 owned_by_ = nullptr;
59 }
60
61
63 {
64 }
65
66
68 {
69 ++iteration_count_;
70 }
71
72
74 {
75 --iteration_count_;
76
77 if( iteration_count_ == 0 )
78 collect();
79 }
80
81
83 {
84 return iteration_count_ != 0;
85 }
86
87
89 {
90 assert( !is_iterating() );
91 observers_.push_back( observer );
92 }
93
94
96 {
97 auto it = std::find( observers_.begin(), observers_.end(), observer );
98
99 if( it == observers_.end() )
100 {
101 assert( false );
102 return;
103 }
104
105 if( is_iterating() )
106 *it = nullptr;
107 else
108 observers_.erase( it );
109 }
110
111
113 {
114 auto it = std::remove_if( observers_.begin(), observers_.end(), DETAIL::equals<void*>( nullptr ) );
115 observers_.erase( it, observers_.end() );
116 }
117 }
118
119
121 : observer_( nullptr )
122 {
123 }
124
125
126 LINK::LINK( std::shared_ptr<DETAIL::OBSERVABLE_BASE::IMPL> token, void* observer )
127 : token_( std::move( token ) ), observer_( observer )
128 {
129 }
130
131
132 LINK::LINK( LINK&& other )
133 : token_( std::move( other.token_ ) ), observer_( other.observer_ )
134 {
135 other.token_.reset();
136 }
137
138
140 {
141 token_ = std::move( other.token_ );
142 other.token_.reset();
143 observer_ = other.observer_;
144 return *this;
145 }
146
147
148 LINK::operator bool() const
149 {
150 return token_ ? true : false;
151 }
152
153
155 {
156 reset();
157 }
158
159
161 {
162 if(token_)
163 {
164 token_->remove_observer( observer_ );
165 token_.reset();
166 }
167 }
168
169
170 namespace DETAIL {
171
173 {
174 }
175
176
178 : impl_( other.get_shared_impl() )
179 {
180 }
181
182
184 {
185 }
186
187
189 {
190 if(!impl_)
191 impl_ = std::make_shared<IMPL>( this );
192 }
193
194
196 {
197 if(!impl_)
198 impl_ = std::make_shared<IMPL>();
199 else
200 impl_->set_shared();
201 }
202
203
205 impl_.reset();
206 }
207
208
209 std::shared_ptr<OBSERVABLE_BASE::IMPL> OBSERVABLE_BASE::get_shared_impl()
210 {
212 return impl_;
213 }
214
215
216 void OBSERVABLE_BASE::add_observer( void* observer )
217 {
219 impl_->add_observer( observer );
220 }
221
222
223 void OBSERVABLE_BASE::remove_observer( void* observer )
224 {
225 assert( impl_ );
226 impl_->remove_observer( observer );
227 }
228
229
231 {
232 if( impl_ )
233 impl_->enter_iteration();
234 }
235
236
238 {
239 if( impl_)
240 {
241 impl_->leave_iteration();
242
243 if( !impl_->is_iterating() && !impl_->is_shared() && impl_.use_count() == 1 )
244 impl_.reset();
245 }
246 }
247
248
250 {
251 if( impl_ )
252 return impl_->observers_.size();
253 else
254 return 0;
255 }
256
257
259 {
260 // called by an impl that is owned by this, ie. it is a non-shared impl
261 // also it is not iterating
263 }
264
265 }
266
267}
A model subscriber implementation using links to represent connections.
Definition: observable.cpp:27
Definition: bitmap.cpp:64
void remove_observer(void *observer)
Definition: observable.cpp:95
void add_observer(void *observer)
Definition: observable.cpp:88
IMPL(OBSERVABLE_BASE *owned_by=nullptr)
Definition: observable.cpp:45
void remove_observer(void *observer)
Definition: observable.cpp:223
std::shared_ptr< IMPL > get_shared_impl()
Definition: observable.cpp:209
void add_observer(void *observer)
Definition: observable.cpp:216
std::shared_ptr< IMPL > impl_
Definition: observable.h:93
equals(const T &val)
Definition: observable.cpp:33
bool operator()(const T &val) const
Definition: observable.cpp:35