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
21 #include <sigc++/functors/slot_base.h>
22
23 namespace sigc
24 {
25
26 namespace internal {
27
28 // only MSVC needs this to guarantee that all new/delete are executed from the DLL module
29 #ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY
operator new(size_t size_)30 void* slot_rep::operator new(size_t size_)
31 {
32 return malloc(size_);
33 }
34
operator delete(void * p)35 void slot_rep::operator delete(void* p)
36 {
37 free(p);
38 }
39 #endif
40
disconnect()41 void slot_rep::disconnect()
42 {
43 if (parent_)
44 {
45 call_ = 0; // Invalidate the slot.
46 // _Must_ be done here because parent_ might defer the actual
47 // destruction of the slot_rep and try to invoke it before that point.
48 void* data_ = parent_;
49 parent_ = 0; // Just a precaution.
50 (cleanup_)(data_); // Notify the parent (might lead to destruction of this!).
51 }
52 else
53 call_ = 0;
54 }
55
56 //static
notify(void * data)57 void* slot_rep::notify(void* data)
58 {
59 slot_rep* self_ = reinterpret_cast<slot_rep*>(data);
60
61 self_->call_ = 0; // Invalidate the slot.
62 self_->destroy(); // Detach the stored functor from the other referred trackables and destroy it.
63 self_->disconnect(); // Disconnect the slot (might lead to deletion of self_!).
64
65 return 0;
66 }
67
68 } // namespace internal
69
slot_base()70 slot_base::slot_base()
71 : rep_(0),
72 blocked_(false)
73 {}
74
slot_base(rep_type * rep)75 slot_base::slot_base(rep_type* rep)
76 : rep_(rep),
77 blocked_(false)
78 {}
79
slot_base(const slot_base & src)80 slot_base::slot_base(const slot_base& src)
81 : rep_(0),
82 blocked_(src.blocked_)
83 {
84 if (src.rep_)
85 {
86 //Check call_ so we can ignore invalidated slots.
87 //Otherwise, destroyed bound reference parameters (whose destruction caused the slot's invalidation) may be used during dup().
88 //Note: I'd prefer to check somewhere during dup(). murrayc.
89 if (src.rep_->call_)
90 rep_ = src.rep_->dup();
91 else
92 {
93 *this = slot_base(); //Return the default invalid slot.
94 }
95 }
96 }
97
~slot_base()98 slot_base::~slot_base()
99 {
100 if (rep_)
101 delete rep_;
102 }
103
operator bool() const104 slot_base::operator bool() const
105 {
106 return rep_ != 0;
107 }
108
operator =(const slot_base & src)109 slot_base& slot_base::operator=(const slot_base& src)
110 {
111 if (src.rep_ == rep_) return *this;
112
113 if (src.empty())
114 {
115 disconnect();
116 return *this;
117 }
118
119 internal::slot_rep* new_rep_ = src.rep_->dup();
120
121 if (rep_) // Silently exchange the slot_rep.
122 {
123 new_rep_->set_parent(rep_->parent_, rep_->cleanup_);
124 delete rep_;
125 }
126
127 rep_ = new_rep_;
128
129 return *this;
130 }
131
set_parent(void * parent,void * (* cleanup)(void *)) const132 void slot_base::set_parent(void* parent, void* (*cleanup)(void*)) const
133 {
134 if (rep_)
135 rep_->set_parent(parent, cleanup);
136 }
137
add_destroy_notify_callback(void * data,func_destroy_notify func) const138 void slot_base::add_destroy_notify_callback(void* data, func_destroy_notify func) const
139 {
140 if (rep_)
141 rep_->add_destroy_notify_callback(data, func);
142 }
143
remove_destroy_notify_callback(void * data) const144 void slot_base::remove_destroy_notify_callback(void* data) const
145 {
146 if (rep_)
147 rep_->remove_destroy_notify_callback(data);
148 }
149
block(bool should_block)150 bool slot_base::block(bool should_block)
151 {
152 bool old = blocked_;
153 blocked_ = should_block;
154 return old;
155 }
156
unblock()157 bool slot_base::unblock()
158 {
159 return block(false);
160 }
161
disconnect()162 void slot_base::disconnect()
163 {
164 if (rep_)
165 rep_->disconnect();
166 }
167
168
169 /*bool slot_base::empty() const // having this function not inline is killing performance !!!
170 {
171 if (rep_ && !rep_->call_)
172 {
173 delete rep_; // This is not strictly necessary here. I'm convinced that it is
174 rep_ = 0; // safe to wait for the destructor to delete the slot_rep. Martin.
175 }
176 return (rep_ == 0);
177 }*/
178
179 } //namespace sigc
180