1 // -*- c++ -*-
2 /*
3 * Copyright 2003, The libsigc++ Development Team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20 #include <sigc++/signal_base.h>
21
22 namespace sigc {
23 namespace internal {
24
signal_impl()25 signal_impl::signal_impl()
26 : ref_count_(0), exec_count_(0), deferred_(0)
27 {}
28
29 // only MSVC needs this to guarantee that all new/delete are executed from the DLL module
30 #ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY
operator new(size_t size_)31 void* signal_impl::operator new(size_t size_)
32 {
33 return malloc(size_);
34 }
35
operator delete(void * p)36 void signal_impl::operator delete(void* p)
37 {
38 free(p);
39 }
40 #endif
41
clear()42 void signal_impl::clear()
43 {
44 slots_.clear();
45 }
46
size() const47 signal_impl::size_type signal_impl::size() const
48 {
49 return slots_.size();
50 }
51
connect(const slot_base & slot_)52 signal_impl::iterator_type signal_impl::connect(const slot_base& slot_)
53 {
54 return insert(slots_.end(), slot_);
55 }
56
erase(iterator_type i)57 signal_impl::iterator_type signal_impl::erase(iterator_type i)
58 {
59 return slots_.erase(i);
60 }
61
insert(signal_impl::iterator_type i,const slot_base & slot_)62 signal_impl::iterator_type signal_impl::insert(signal_impl::iterator_type i, const slot_base& slot_)
63 {
64 iterator_type temp = slots_.insert(i, slot_);
65 temp->set_parent(this, ¬ify);
66 return temp;
67 }
68
sweep()69 void signal_impl::sweep()
70 {
71 deferred_ = false;
72 iterator_type i = slots_.begin();
73 while (i != slots_.end())
74 if ((*i).empty())
75 i = slots_.erase(i);
76 else
77 ++i;
78 }
79
notify(void * d)80 void* signal_impl::notify(void* d)
81 {
82 signal_impl* self = reinterpret_cast<signal_impl*>(d);
83 if (self->exec_count_ == 0)
84 self->sweep();
85 else // This is occuring during signal emission.
86 self->deferred_ = true; // => sweep() will be called from ~signal_exec().
87 return 0; // This is safer because we don't have to care about our iterators in emit().
88 }
89
90 } /* namespace internal */
91
signal_base()92 signal_base::signal_base()
93 : impl_(0)
94 {}
95
signal_base(const signal_base & src)96 signal_base::signal_base(const signal_base& src)
97 : trackable(),
98 impl_(src.impl())
99 {
100 impl_->reference();
101 }
102
~signal_base()103 signal_base::~signal_base()
104 {
105 if (impl_)
106 impl_->unreference();
107 }
108
clear()109 void signal_base::clear()
110 {
111 if (impl_)
112 impl_->clear();
113 }
114
size() const115 signal_base::size_type signal_base::size() const
116 {
117 return (impl_ ? impl_->size() : 0);
118 }
119
connect(const slot_base & slot_)120 signal_base::iterator_type signal_base::connect(const slot_base& slot_)
121 {
122 return impl()->connect(slot_);
123 }
124
insert(iterator_type i,const slot_base & slot_)125 signal_base::iterator_type signal_base::insert(iterator_type i, const slot_base& slot_)
126 {
127 return impl()->insert(i, slot_);
128 }
129
erase(iterator_type i)130 signal_base::iterator_type signal_base::erase(iterator_type i)
131 {
132 return impl()->erase(i);
133 }
134
operator =(const signal_base & src)135 signal_base& signal_base::operator = (const signal_base& src)
136 {
137 if (impl_) impl_->unreference();
138 impl_ = src.impl();
139 impl_->reference();
140 return *this;
141 }
142
impl() const143 internal::signal_impl* signal_base::impl() const
144 {
145 if (!impl_) {
146 impl_ = new internal::signal_impl;
147 impl_->reference(); // start with a reference count of 1
148 }
149 return impl_;
150 }
151
152 } /* sigc */
153