Merged with trunk R1705.
[ardour.git] / libs / sigc++2 / sigc++ / functors / slot_base.cc
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
30 void* slot_rep::operator new(size_t size_)
31 {
32   return malloc(size_);
33 }
34
35 void slot_rep::operator delete(void* p)
36 {
37   free(p);
38 }
39 #endif
40
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 }
53
54 //static
55 void* slot_rep::notify(void* data)
56 {
57   slot_rep* self_ = (slot_rep*)data;
58   self_->call_ = 0; // Invalidate the slot.
59   self_->destroy(); // Detach the stored functor from the other referred trackables and destroy it.
60   self_->disconnect(); // Disconnect the slot (might lead to deletion of self_!).
61   return 0;
62 }
63
64 } // namespace internal
65   
66 slot_base::slot_base()
67 : rep_(0),
68   blocked_(false)
69 {}
70
71 slot_base::slot_base(rep_type* rep)
72 : rep_(rep),
73   blocked_(false)
74 {}
75
76 slot_base::slot_base(const slot_base& src)
77 : rep_(0),
78   blocked_(src.blocked_)
79 {
80   if (src.rep_)
81     rep_ = src.rep_->dup();
82 }
83
84 slot_base::~slot_base()
85 {
86   if (rep_)
87     delete rep_;
88 }
89
90 slot_base::operator bool() const
91 {
92   return rep_ != 0;
93 }
94
95 slot_base& slot_base::operator=(const slot_base& src)
96 {
97   if (src.rep_ == rep_) return *this;
98
99   if (src.empty())
100   {
101     disconnect();
102     return *this;
103   }
104
105   internal::slot_rep* new_rep_ = src.rep_->dup();
106
107   if (rep_)               // Silently exchange the slot_rep.
108   {
109     new_rep_->set_parent(rep_->parent_, rep_->cleanup_);
110     delete rep_;
111   }
112
113   rep_ = new_rep_;
114
115   return *this;
116 }
117
118 void slot_base::set_parent(void* parent, void* (*cleanup)(void*)) const
119 {
120   if (rep_)
121     rep_->set_parent(parent, cleanup);
122 }
123
124 void slot_base::add_destroy_notify_callback(void* data, func_destroy_notify func) const
125 {
126   if (rep_)
127     rep_->add_destroy_notify_callback(data, func);
128 }
129
130 void slot_base::remove_destroy_notify_callback(void* data) const
131 {
132   if (rep_)
133     rep_->remove_destroy_notify_callback(data);
134 }
135
136 bool slot_base::block(bool should_block)
137 {
138   bool old = blocked_;
139   blocked_ = should_block;
140   return old;
141 }
142
143 bool slot_base::unblock()
144 {
145   return block(false);
146 }
147
148 void slot_base::disconnect()
149 {
150   if (rep_)
151     rep_->disconnect();
152 }
153
154
155 /*bool slot_base::empty() const // having this function not inline is killing performance !!!
156 {
157   if (rep_ && !rep_->call_)
158     {
159       delete rep_;        // This is not strictly necessary here. I'm convinced that it is
160       rep_ = 0;           // safe to wait for the destructor to delete the slot_rep. Martin.
161     }
162   return (rep_ == 0);
163 }*/
164
165 } //namespace sigc