00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_NUB_SIGNAL_CC_UTC20050626084019_DEFINED
00035 #define GROOVX_NUB_SIGNAL_CC_UTC20050626084019_DEFINED
00036
00037 #include "signal.h"
00038
00039 #include "nub/ref.h"
00040
00041 #include "rutz/demangle.h"
00042
00043 #include <list>
00044 #include <typeinfo>
00045
00046 #include "rutz/trace.h"
00047 #include "rutz/debug.h"
00048 GVX_DBG_REGISTER
00049
00051
00052
00053
00055
00056 nub::slot_base::slot_base()
00057 {
00058 GVX_TRACE("nub::slot_base::slot_base");
00059 }
00060
00061 nub::slot_base::~slot_base() throw()
00062 {
00063 GVX_TRACE("nub::slot_base::~slot_base");
00064 }
00065
00066 bool nub::slot_base::exists() const
00067 {
00068 GVX_TRACE("nub::slot_base::exists");
00069 return true;
00070 }
00071
00073
00074
00075
00077
00078 nub::slot0::slot0()
00079 {
00080 GVX_TRACE("nub::slot0::slot0");
00081 }
00082
00083 nub::slot0::~slot0() throw()
00084 {
00085 GVX_TRACE("nub::slot0::~slot0");
00086 }
00087
00088 nub::soft_ref<nub::slot0> nub::slot0::make(void (*free_func)())
00089 {
00090 GVX_TRACE("nub::slot0::make");
00091
00092 return nub::soft_ref<slot0>(slot_adapter_free_func0::make(free_func));
00093 }
00094
00095 nub::slot_adapter_free_func0::slot_adapter_free_func0(free_func* f)
00096 : m_free_func(f)
00097 {}
00098
00099 nub::slot_adapter_free_func0::~slot_adapter_free_func0() throw() {}
00100
00101 nub::slot_adapter_free_func0*
00102 nub::slot_adapter_free_func0::make(free_func* f)
00103 {
00104 return new slot_adapter_free_func0(f);
00105 }
00106
00107 void nub::slot_adapter_free_func0::call()
00108 {
00109 (*m_free_func)();
00110 }
00111
00113
00114
00115
00117
00118 namespace
00119 {
00120 typedef nub::ref<nub::slot_base> slot_ref;
00121 }
00122
00123 struct nub::signal_base::impl
00124 {
00125 public:
00126 impl() :
00127 slots(),
00128 is_emitting(false)
00129 {}
00130
00131 virtual ~impl() {}
00132
00133 typedef std::list<slot_ref> list_type;
00134
00135 list_type slots;
00136 bool is_emitting;
00137
00138 class locker
00139 {
00140 locker(const locker&);
00141 locker& operator=(const locker&);
00142
00143 impl* m_target;
00144
00145 public:
00146 locker(impl* impl) :
00147 m_target(impl)
00148 {
00149 GVX_ASSERT(m_target->is_emitting == false);
00150 m_target->is_emitting = true;
00151 }
00152
00153 ~locker()
00154 {
00155 GVX_ASSERT(m_target->is_emitting == true);
00156 m_target->is_emitting = false;
00157 }
00158 };
00159 };
00160
00161 nub::signal_base::signal_base() :
00162 nub::volatile_object(),
00163 rep(new impl)
00164 {}
00165
00166 nub::signal_base::~signal_base() throw()
00167 {
00168 delete rep;
00169 }
00170
00171 void nub::signal_base::do_emit(void* params) const
00172 {
00173 GVX_TRACE("nub::signal_base::do_emit");
00174 if (!rep->is_emitting)
00175 {
00176 impl::locker lock(rep);
00177
00178 for (impl::list_type::iterator
00179 ii = rep->slots.begin(), end = rep->slots.end();
00180 ii != end;
00181 )
00182 {
00183 dbg_eval(3, typeid(**ii).name());
00184 dbg_eval_nl(3, (*ii)->dbg_ref_count());
00185 dbg_eval_nl(3, (*ii)->exists());
00186 if ((*ii)->exists())
00187 {
00188 (*ii)->do_call(params);
00189 ++ii;
00190 }
00191 else
00192 {
00193 impl::list_type::iterator erase_me = ii;
00194 ++ii;
00195 rep->slots.erase(erase_me);
00196 }
00197 }
00198 }
00199 }
00200
00201 void nub::signal_base::do_disconnect(nub::soft_ref<nub::slot_base> slot)
00202 {
00203 GVX_TRACE("nub::signal_base::do_disconnect");
00204 if (!slot.is_valid()) return;
00205
00206 rep->slots.remove(slot_ref(slot.get(), nub::PRIVATE));
00207
00208 dbg_eval_nl(3, rep->slots.size());
00209 }
00210
00211 void nub::signal_base::do_connect(nub::soft_ref<nub::slot_base> slot)
00212 {
00213 GVX_TRACE("nub::signal_base::do_connect");
00214 if (!slot.is_valid()) return;
00215
00216 rep->slots.push_back(slot_ref(slot.get(), nub::PRIVATE));
00217
00218 dbg_eval_nl(3, rep->slots.size());
00219 }
00220
00222
00223
00224
00226
00227 nub::signal0::signal0() :
00228 signal_base(),
00229 slot_emit_self(slot0::make(this, &nub::signal0::emit))
00230 {
00231 GVX_TRACE("nub::signal0::signal0");
00232 }
00233
00234 nub::signal0::~signal0() throw()
00235 {
00236 GVX_TRACE("nub::signal0::~signal0");
00237 }
00238
00239 static const char __attribute__((used)) vcid_groovx_nub_signal_cc_utc20050626084019[] = "$Id: signal.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00240 #endif // !GROOVX_NUB_SIGNAL_CC_UTC20050626084019_DEFINED