blob: 1b2b1d2665a5070413464d57b4b74dd318bfd145 [file] [log] [blame]
/*
*
* D-Bus++ - C++ bindings for D-Bus
*
* Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com>
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __DBUSXX_DISPATCHER_H
#define __DBUSXX_DISPATCHER_H
#include "api.h"
#include "connection.h"
#include "eventloop.h"
namespace DBus {
class DXXAPI Timeout
{
public:
class Internal;
Timeout(Internal *i);
virtual ~Timeout(){}
/*!
* \brief Gets the timeout interval.
*
* The dbus_timeout_handle() should be called each time this interval elapses,
* starting after it elapses once.
*
* The interval may change during the life of the timeout; if so, the timeout
* will be disabled and re-enabled (calling the "timeout toggled function") to
* notify you of the change.
*
* return The interval in miliseconds.
*/
int interval() const;
bool enabled() const;
/*!
* \brief Calls the timeout handler for this timeout.
*
* This function should be called when the timeout occurs.
*
* If this function returns FALSE, then there wasn't enough memory to handle
* the timeout. Typically just letting the timeout fire again next time it
* naturally times out is an adequate response to that problem, but you could
* try to do more if you wanted.
*
* return false If there wasn't enough memory.
*/
bool handle();
virtual void toggle() = 0;
private:
DXXAPILOCAL Timeout(const Timeout &);
private:
Internal *_int;
};
class DXXAPI Watch
{
public:
class Internal;
Watch(Internal *i);
virtual ~Watch(){}
/*!
* \brief A main loop could poll this descriptor to integrate dbus-c++.
*
* This function calls dbus_watch_get_socket() on win32 and
* dbus_watch_get_unix_fd() on all other systems. (see dbus documentation)
*
* @return The file descriptor.
*/
int descriptor() const;
/*!
* \brief Gets flags from DBusWatchFlags indicating what conditions should be
* monitored on the file descriptor.
*
* The flags returned will only contain DBUS_WATCH_READABLE and DBUS_WATCH_WRITABLE,
* never DBUS_WATCH_HANGUP or DBUS_WATCH_ERROR; all watches implicitly include
* a watch for hangups, errors, and other exceptional conditions.
*
* @return The conditions to watch.
*/
int flags() const;
bool enabled() const;
/*!
* \brief Called to notify the D-Bus library when a previously-added watch
* is ready for reading or writing, or has an exception such as a hangup.
*
* If this function returns FALSE, then the file descriptor may still be
* ready for reading or writing, but more memory is needed in order to do the
* reading or writing. If you ignore the FALSE return, your application may
* spin in a busy loop on the file descriptor until memory becomes available,
* but nothing more catastrophic should happen.
*
* dbus_watch_handle() cannot be called during the DBusAddWatchFunction, as the
* connection will not be ready to handle that watch yet.
*
* It is not allowed to reference a DBusWatch after it has been passed to remove_function.
*
* @param flags The poll condition using DBusWatchFlags values.
* @return false If there wasn't enough memory.
*/
bool handle(int flags);
virtual void toggle() = 0;
private:
DXXAPILOCAL Watch(const Watch &);
private:
Internal *_int;
};
class DXXAPI Dispatcher
{
public:
Dispatcher() : _dispatching(false) {}
virtual ~Dispatcher()
{}
void queue_connection(Connection::Private *);
void dispatch_pending();
bool has_something_to_dispatch();
virtual void enter() = 0;
virtual void leave() = 0;
virtual Timeout *add_timeout(Timeout::Internal *) = 0;
virtual void rem_timeout(Timeout *) = 0;
virtual Watch *add_watch(Watch::Internal *) = 0;
virtual void rem_watch(Watch *) = 0;
struct Private;
private:
DefaultMutex _mutex_p;
Connection::PrivatePList _pending_queue;
bool _dispatching;
};
extern DXXAPI Dispatcher *default_dispatcher;
/* classes for multithreading support
*/
class DXXAPI Mutex
{
public:
virtual ~Mutex() {}
virtual void lock() = 0;
virtual void unlock() = 0;
struct Internal;
protected:
Internal *_int;
};
class DXXAPI CondVar
{
public:
virtual ~CondVar() {}
virtual void wait(Mutex *) = 0;
virtual bool wait_timeout(Mutex *, int timeout) = 0;
virtual void wake_one() = 0;
virtual void wake_all() = 0;
struct Internal;
protected:
Internal *_int;
};
typedef Mutex *(*MutexNewFn)();
typedef void (*MutexUnlockFn)(Mutex *mx);
#ifndef DBUS_HAS_RECURSIVE_MUTEX
typedef bool (*MutexFreeFn)(Mutex *mx);
typedef bool (*MutexLockFn)(Mutex *mx);
#else
typedef void (*MutexFreeFn)(Mutex *mx);
typedef void (*MutexLockFn)(Mutex *mx);
#endif//DBUS_HAS_RECURSIVE_MUTEX
typedef CondVar *(*CondVarNewFn)();
typedef void (*CondVarFreeFn)(CondVar *cv);
typedef void (*CondVarWaitFn)(CondVar *cv, Mutex *mx);
typedef bool (*CondVarWaitTimeoutFn)(CondVar *cv, Mutex *mx, int timeout);
typedef void (*CondVarWakeOneFn)(CondVar *cv);
typedef void (*CondVarWakeAllFn)(CondVar *cv);
void DXXAPI _init_threading();
void DXXAPI _init_threading(
MutexNewFn, MutexFreeFn, MutexLockFn, MutexUnlockFn,
CondVarNewFn, CondVarFreeFn, CondVarWaitFn, CondVarWaitTimeoutFn, CondVarWakeOneFn, CondVarWakeAllFn
);
template<class Mx, class Cv>
struct Threading
{
static void init()
{
_init_threading(
mutex_new, mutex_free, mutex_lock, mutex_unlock,
condvar_new, condvar_free, condvar_wait, condvar_wait_timeout, condvar_wake_one, condvar_wake_all
);
}
static Mutex *mutex_new()
{
return new Mx;
}
#ifndef DBUS_HAS_RECURSIVE_MUTEX
static bool mutex_free(Mutex *mx)
{
delete mx;
return false;
}
static bool mutex_lock(Mutex *mx)
{
mx->lock();
return false;
}
#else
static void mutex_free(Mutex *mx)
{
delete mx;
}
static void mutex_lock(Mutex *mx)
{
mx->lock();
}
#endif//DBUS_HAS_RECURSIVE_MUTEX
static void mutex_unlock(Mutex *mx)
{
mx->unlock();
}
static CondVar *condvar_new()
{
return new Cv;
}
static void condvar_free(CondVar *cv)
{
delete cv;
}
static void condvar_wait(CondVar *cv, Mutex *mx)
{
cv->wait(mx);
}
static bool condvar_wait_timeout(CondVar *cv, Mutex *mx, int timeout)
{
return cv->wait_timeout(mx, timeout);
}
static void condvar_wake_one(CondVar *cv)
{
cv->wake_one();
}
static void condvar_wake_all(CondVar *cv)
{
cv->wake_all();
}
};
} /* namespace DBus */
#endif//__DBUSXX_DISPATCHER_H