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, &notify);
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