3 * D-Bus++ - C++ bindings for D-Bus
5 * Copyright (C) 2005-2009 Paolo Durante <shackan@gmail.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #ifndef __DBUSXX_UTIL_H
26 #define __DBUSXX_UTIL_H
39 * Very simple reference counting
42 class DBUSXXAPI RefCnt
50 __mtx
= new pthread_mutex_t
;
51 pthread_mutex_init(__mtx
, NULL
);
54 RefCnt(const RefCnt
&rc
)
66 RefCnt
&operator = (const RefCnt
&ref
)
92 pthread_mutex_lock(__mtx
);
100 pthread_mutex_unlock(__mtx
);
106 DBUSXXAPILOCAL
void ref() const
110 DBUSXXAPILOCAL
void unref()
116 debug_log("%p: refcount dropped below zero!", __ref
);
123 pthread_mutex_destroy(__mtx
);
132 pthread_mutex_t
* __mtx
;
136 * Pthreads-based mutual exclusion
144 Guard(const Synchronized
*s
) : _s(s
)
152 const Synchronized
*_s
;
157 pthread_mutex_lock(&__mtx
);
162 pthread_mutex_unlock(&__mtx
);
169 pthread_mutex_init(&__mtx
, NULL
);
176 pthread_mutex_destroy(&__mtx
);
181 // Not supported - unimplemented
182 Synchronized(const Synchronized
& lhs
);
183 Synchronized
& operator=(const Synchronized
& ref
);
185 mutable pthread_mutex_t __mtx
;
189 * Reference counting pointers (emulate boost::shared_ptr)
196 RefPtrVoid(void *ptr
)
201 RefPtrVoid(const RefPtrVoid
& lhs
)
206 virtual ~RefPtrVoid()
209 bool operator == (const RefPtrVoid
&ref
) const
211 return __ptr
== ref
.__ptr
;
221 class RefPtrI
: public RefPtrVoid
// RefPtr to incomplete type
227 RefPtrI(const RefPtrI
& lhs
);
231 RefPtrI
&operator = (const RefPtrI
&ref
)
237 // If there is only a single reference (that's us) then ...
244 // If "ref" is referencing something other than what we're
246 if ( __ptr
!= ref
.__ptr
)
254 // At this point __cnt == __ref.__cnt so unlocking __cnt
255 // effectively unlocks ref.__cnt as well.
261 T
&operator *() const
266 T
*operator ->() const
273 return static_cast<T
*>(__ptr
);
278 class RefPtr
: public RefPtrVoid
295 if (__cnt
.one()) delete get();
299 RefPtr
&operator = (const RefPtr
&ref
)
305 // If there is only a single reference (that's us) then ...
312 // If "ref" is referencing something other than what we're
314 if ( __ptr
!= ref
.__ptr
)
322 // At this point __cnt == __ref.__cnt so unlocking __cnt
323 // effectively unlocks ref.__cnt as well.
329 T
&operator *() const
334 T
*operator ->() const
341 return static_cast<T
*>(__ptr
);
346 * Typed callback template
350 // Forward Declarations
352 class CallbackEmitter
;
353 class CallbackTarget
;
355 class CallbackEmitter
: protected Synchronized
359 virtual ~CallbackEmitter();
362 void connect(CallbackTarget
* tgt
);
366 bool isConnected() const;
369 CallbackTarget
* target
;
370 friend class CallbackTarget
;
373 class CallbackTarget
: protected Synchronized
377 virtual ~CallbackTarget();
380 void disconnect_emitter(CallbackEmitter
* cbEmitter
);
381 void connect_emitter(CallbackEmitter
* cbEmitter
);
383 typedef std::set
<CallbackEmitter
*> EmitterCollection
;
384 EmitterCollection emitters
;
385 friend class CallbackEmitter
;
389 // CallbackTarget Implementation
391 inline CallbackTarget::CallbackTarget()
395 debug_log("CallbackTarget(%p)::Constructed");
398 inline CallbackTarget::~CallbackTarget()
401 EmitterCollection::const_iterator it
;
402 // Tell all the callback emitters that this target is
403 // being disconnected.
404 debug_log("CallbackTarget(%p)::# Emitters to disconnect: %u",
405 this, emitters
.size());
407 for ( it
= emitters
.begin(); it
!= emitters
.end(); ++it
)
409 debug_log("CallbackTarget(%p)::Disconnect emitter: %p", this, *it
);
413 debug_log("CallbackTarget(%p)::Destroyed", this);
416 inline void CallbackTarget::disconnect_emitter(CallbackEmitter
* cbEmitter
)
419 debug_log("CallbackTarget(%p)::Erasing emitter: %p", this, cbEmitter
);
420 emitters
.erase(cbEmitter
);
423 inline void CallbackTarget::connect_emitter(CallbackEmitter
* cbEmitter
)
426 debug_log("CallbackTarget(%p)::Inserting emitter: %p", this, cbEmitter
);
427 emitters
.insert(cbEmitter
);
431 // CallbackEmitter Implementation
434 inline CallbackEmitter::CallbackEmitter()
438 debug_log("CallbackEmitter(%p)::Constructed", this);
441 inline CallbackEmitter::~CallbackEmitter()
447 debug_log("CallbackEmitter(%p)::Disconnecting from target: %p", this, target
);
448 target
->disconnect_emitter(this);
451 debug_log("CallbackEmitter(%p)::Destroyed", this);
454 inline void CallbackEmitter::connect(CallbackTarget
* tgt
)
458 if ( target
&& (target
!= tgt
) )
460 // Unregister from the (old) target first
461 debug_log("CallbackEmitter(%p)::Unregistering emitter from target: %p", this, target
);
462 target
->disconnect_emitter(this);
468 debug_log("CallbackEmitter(%p)::Connecting to target: %p", this, target
);
469 target
->connect_emitter(this);
473 inline void CallbackEmitter::disconnect()
476 debug_log("CallbackEmitter(%p)::Disconnecting target: %p", this, target
);
480 inline bool CallbackEmitter::isConnected() const
486 template <class R
, class P
>
487 class Callback_Base
: public CallbackEmitter
490 Callback_Base() : CallbackEmitter() {}
492 virtual R
call(P param
) const = 0;
494 virtual ~Callback_Base()
498 template <class R
, class P
>
503 Slot
&operator = (Callback_Base
<R
,P
>* s
)
510 R
operator()(P param
) const
512 /*if (_cb.get())*/ return _cb
->call(param
);
515 R
call(P param
) const
517 /*if (_cb.get())*/ return _cb
->call(param
);
522 return _cb
.get() == 0;
527 RefPtr
< Callback_Base
<R
,P
> > _cb
;
531 template <class C
, class P
>
532 class CallbackNoReturn
: public Callback_Base
<void,P
>
536 typedef void (C::*M
)(P
);
538 CallbackNoReturn(C
*c
, M m
)
541 debug_log("CallbackNoReturn(%p)::Ctor - connect to target: %p", this, c
);
542 CallbackEmitter::connect(c
);
545 virtual ~CallbackNoReturn()
547 debug_log("CallbackNoReturn(%p)::Destroyed", this);
550 void call(P param
) const
552 Synchronized::Guard
g(this);
554 if ( CallbackEmitter::isConnected() )
566 template <class C
, class R
, class P
>
567 class Callback
: public Callback_Base
<R
,P
>
571 typedef R (C::*M
)(P
);
573 Callback(C
*c
, M m
, const R
& def
)
574 : _c(c
), _m(m
), _d(def
)
576 debug_log("Callback(%p)::Ctor - connect to target: %p", this, c
);
577 CallbackEmitter::connect(c
);
582 debug_log("Callback(%p)::Destroyed", this);
585 R
call(P param
) const
587 Synchronized::Guard
g(this);
589 if ( CallbackEmitter::isConnected() )
591 return (_c
->*_m
)(param
);
601 } /* namespace DBus */
603 #endif//__DBUSXX_UTIL_H