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
33 #include <ext/atomicity.h>
43 // Platform independent atomic support
50 typedef unsigned tAtomicCnt
;
52 AtomicCounter(tAtomicCnt init_val
):
58 return atomic_add_value(&_counter
, 0U);
63 atomic_add(&_counter
, 1);
68 atomic_sub(&_counter
, 1);
72 volatile tAtomicCnt _counter
;
75 #elif defined(__GNUC__)
80 typedef _Atomic_word tAtomicCnt
;
82 AtomicCounter(tAtomicCnt init_val
):
88 return __gnu_cxx::__exchange_and_add(&_counter
, 0);
93 __gnu_cxx::__atomic_add(&_counter
, +1);
98 __gnu_cxx::__atomic_add(&_counter
, -1);
102 volatile tAtomicCnt _counter
;
106 #error Atomic operations are not defined for this OS and/or compiler
110 * Very simple reference counting
113 class DBUSXXAPI RefCnt
119 __ref
= new AtomicCounter(1);
122 RefCnt(const RefCnt
&rc
)
133 RefCnt
&operator = (const RefCnt
&ref
)
146 return (*__ref
) == 0;
151 return (*__ref
) == 1;
156 DBUSXXAPILOCAL
void ref() const
161 DBUSXXAPILOCAL
void unref()
167 debug_log("%p: refcount dropped below zero!", __ref
);
179 AtomicCounter
* __ref
;
183 * Pthreads-based mutual exclusion
191 Guard(const Synchronized
*s
) : _s(s
)
199 const Synchronized
*_s
;
204 pthread_mutex_lock(&__mtx
);
209 pthread_mutex_unlock(&__mtx
);
216 pthread_mutex_init(&__mtx
, NULL
);
223 pthread_mutex_destroy(&__mtx
);
228 // Not supported - unimplemented
229 Synchronized(const Synchronized
& lhs
);
230 Synchronized
& operator=(const Synchronized
& ref
);
232 mutable pthread_mutex_t __mtx
;
236 * Reference counting pointers (emulate boost::shared_ptr)
243 RefPtrVoid(void *ptr
)
248 RefPtrVoid(const RefPtrVoid
& lhs
)
253 virtual ~RefPtrVoid()
256 bool operator == (const RefPtrVoid
&ref
) const
258 return __ptr
== ref
.__ptr
;
268 class RefPtrI
: public RefPtrVoid
// RefPtr to incomplete type
274 RefPtrI(const RefPtrI
<T
>& lhs
);
278 RefPtrI
<T
>& operator = (const RefPtrI
<T
> &ref
);
280 T
&operator *() const
285 T
*operator ->() const
292 return static_cast<T
*>(__ptr
);
297 class RefPtr
: public RefPtrVoid
305 RefPtr(const RefPtr
<T
>& lhs
)
313 if (__cnt
.one()) delete get();
316 RefPtr
<T
>& operator = (const RefPtr
<T
>& ref
)
320 // If there is only a single reference (that's us) then ...
332 T
&operator *() const
337 T
*operator ->() const
344 return static_cast<T
*>(__ptr
);
349 * Typed callback template
353 // Forward Declarations
355 class CallbackEmitter
;
356 class CallbackTarget
;
358 class CallbackEmitter
: protected Synchronized
362 virtual ~CallbackEmitter();
365 void connect(CallbackTarget
* tgt
);
369 bool isConnected() const;
372 CallbackTarget
* target
;
373 friend class CallbackTarget
;
376 class CallbackTarget
: protected Synchronized
380 virtual ~CallbackTarget();
383 void disconnect_emitter(CallbackEmitter
* cbEmitter
);
384 void connect_emitter(CallbackEmitter
* cbEmitter
);
386 typedef std::set
<CallbackEmitter
*> EmitterCollection
;
387 EmitterCollection emitters
;
388 friend class CallbackEmitter
;
392 // CallbackTarget Implementation
394 inline CallbackTarget::CallbackTarget()
398 debug_log("CallbackTarget(%p)::Constructed");
401 inline CallbackTarget::~CallbackTarget()
404 EmitterCollection::const_iterator it
;
405 // Tell all the callback emitters that this target is
406 // being disconnected.
407 debug_log("CallbackTarget(%p)::# Emitters to disconnect: %u",
408 this, emitters
.size());
410 for ( it
= emitters
.begin(); it
!= emitters
.end(); ++it
)
412 debug_log("CallbackTarget(%p)::Disconnect emitter: %p", this, *it
);
416 debug_log("CallbackTarget(%p)::Destroyed", this);
419 inline void CallbackTarget::disconnect_emitter(CallbackEmitter
* cbEmitter
)
422 debug_log("CallbackTarget(%p)::Erasing emitter: %p", this, cbEmitter
);
423 emitters
.erase(cbEmitter
);
426 inline void CallbackTarget::connect_emitter(CallbackEmitter
* cbEmitter
)
429 debug_log("CallbackTarget(%p)::Inserting emitter: %p", this, cbEmitter
);
430 emitters
.insert(cbEmitter
);
434 // CallbackEmitter Implementation
437 inline CallbackEmitter::CallbackEmitter()
441 debug_log("CallbackEmitter(%p)::Constructed", this);
444 inline CallbackEmitter::~CallbackEmitter()
450 debug_log("CallbackEmitter(%p)::Disconnecting from target: %p", this, target
);
451 target
->disconnect_emitter(this);
454 debug_log("CallbackEmitter(%p)::Destroyed", this);
457 inline void CallbackEmitter::connect(CallbackTarget
* tgt
)
461 if ( target
&& (target
!= tgt
) )
463 // Unregister from the (old) target first
464 debug_log("CallbackEmitter(%p)::Unregistering emitter from target: %p", this, target
);
465 target
->disconnect_emitter(this);
471 debug_log("CallbackEmitter(%p)::Connecting to target: %p", this, target
);
472 target
->connect_emitter(this);
476 inline void CallbackEmitter::disconnect()
479 debug_log("CallbackEmitter(%p)::Disconnecting target: %p", this, target
);
483 inline bool CallbackEmitter::isConnected() const
489 template <class R
, class P
>
490 class Callback_Base
: public CallbackEmitter
493 Callback_Base() : CallbackEmitter() {}
495 virtual R
call(P param
) const = 0;
497 virtual ~Callback_Base()
501 template <class R
, class P
>
506 Slot
&operator = (Callback_Base
<R
,P
>* s
)
513 R
operator()(P param
) const
515 /*if (_cb.get())*/ return _cb
->call(param
);
518 R
call(P param
) const
520 /*if (_cb.get())*/ return _cb
->call(param
);
525 return _cb
.get() == 0;
530 RefPtr
< Callback_Base
<R
,P
> > _cb
;
534 template <class C
, class P
>
535 class CallbackNoReturn
: public Callback_Base
<void,P
>
539 typedef void (C::*M
)(P
);
541 CallbackNoReturn(C
*c
, M m
)
544 debug_log("CallbackNoReturn(%p)::Ctor - connect to target: %p", this, c
);
545 CallbackEmitter::connect(c
);
548 virtual ~CallbackNoReturn()
550 debug_log("CallbackNoReturn(%p)::Destroyed", this);
553 void call(P param
) const
555 Synchronized::Guard
g(this);
557 if ( CallbackEmitter::isConnected() )
569 template <class C
, class R
, class P
>
570 class Callback
: public Callback_Base
<R
,P
>
574 typedef R (C::*M
)(P
);
576 Callback(C
*c
, M m
, const R
& def
)
577 : _c(c
), _m(m
), _d(def
)
579 debug_log("Callback(%p)::Ctor - connect to target: %p", this, c
);
580 CallbackEmitter::connect(c
);
585 debug_log("Callback(%p)::Destroyed", this);
588 R
call(P param
) const
590 Synchronized::Guard
g(this);
592 if ( CallbackEmitter::isConnected() )
594 return (_c
->*_m
)(param
);
604 } /* namespace DBus */
606 #endif//__DBUSXX_UTIL_H