2003-02-26 Havoc Pennington <hp@pobox.com>

* dbus/dbus-connection.c
	(dbus_connection_send_message_with_reply_and_block): fix crash
	where we ref'd the outgoing message instead of the returned reply

	* dbus/dbus-transport-unix.c (do_authentication): check read watch
	at the end of this function, so if we didn't need to read for
	authentication, we reinstall it for receiving messages

	* dbus/dbus-message.c (dbus_message_new_reply): allow replies to
	a NULL sender for peer-to-peer case

	* dbus/dbus-transport-unix.c (check_read_watch): handle
	!authenticated case correctly

	* glib/dbus-gmain.c: add support for DBusServer

	* dbus/dbus-server.c: add data slot support

	* glib/dbus-gmain.c (dbus_connection_setup_with_g_main): check
	return values and handle errors

	* dbus/dbus-dataslot.c: factor out the data slot stuff from
	DBusConnection

	* Doxyfile.in (INPUT): add glib subdir

	* glib/dbus-gmain.c (dbus_connection_setup_with_g_main): rename
	setup_with_g_main instead of hookup_with_g_main; write docs
This commit is contained in:
Havoc Pennington 2003-02-26 06:42:57 +00:00
parent 3781f063a6
commit 7265423411
21 changed files with 1038 additions and 245 deletions

View file

@ -1,3 +1,34 @@
2003-02-26 Havoc Pennington <hp@pobox.com>
* dbus/dbus-connection.c
(dbus_connection_send_message_with_reply_and_block): fix crash
where we ref'd the outgoing message instead of the returned reply
* dbus/dbus-transport-unix.c (do_authentication): check read watch
at the end of this function, so if we didn't need to read for
authentication, we reinstall it for receiving messages
* dbus/dbus-message.c (dbus_message_new_reply): allow replies to
a NULL sender for peer-to-peer case
* dbus/dbus-transport-unix.c (check_read_watch): handle
!authenticated case correctly
* glib/dbus-gmain.c: add support for DBusServer
* dbus/dbus-server.c: add data slot support
* glib/dbus-gmain.c (dbus_connection_setup_with_g_main): check
return values and handle errors
* dbus/dbus-dataslot.c: factor out the data slot stuff from
DBusConnection
* Doxyfile.in (INPUT): add glib subdir
* glib/dbus-gmain.c (dbus_connection_setup_with_g_main): rename
setup_with_g_main instead of hookup_with_g_main; write docs
2003-02-24 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-marshal.c: (_dbus_marshal_validate_arg):

View file

@ -49,7 +49,7 @@ WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = dbus bus
INPUT = dbus bus glib
FILE_PATTERNS = *.c *.h
RECURSIVE = YES
#EXCLUDE = test

View file

@ -73,6 +73,8 @@ libdbus_1_la_SOURCES= \
noinst_LTLIBRARIES=libdbus-convenience.la
libdbus_convenience_la_SOURCES= \
dbus-dataslot.c \
dbus-dataslot.h \
dbus-hash.c \
dbus-hash.h \
dbus-internals.c \

View file

@ -33,6 +33,7 @@
#include "dbus-message-handler.h"
#include "dbus-threads.h"
#include "dbus-protocol.h"
#include "dbus-dataslot.h"
/**
* @defgroup DBusConnection DBusConnection
@ -66,15 +67,6 @@
static dbus_bool_t _dbus_modify_sigpipe = TRUE;
/** Opaque typedef for DBusDataSlot */
typedef struct DBusDataSlot DBusDataSlot;
/** DBusDataSlot is used to store application data on the connection */
struct DBusDataSlot
{
void *data; /**< The application data */
DBusFreeFunction free_data_func; /**< Free the application data */
};
/**
* Implementation details of DBusConnection. All fields are private.
*/
@ -105,8 +97,8 @@ struct DBusConnection
DBusHashTable *handler_table; /**< Table of registered DBusMessageHandler */
DBusList *filter_list; /**< List of filters. */
DBusDataSlot *data_slots; /**< Data slots */
int n_slots; /**< Slots allocated so far. */
DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */
DBusHashTable *pending_replies; /**< Hash of message serials and their message handlers. */
DBusCounter *connection_counter; /**< Counter that we decrement when finalized */
@ -130,7 +122,6 @@ typedef struct
static void reply_handler_data_free (ReplyHandlerData *data);
static void _dbus_connection_free_data_slots_nolock (DBusConnection *connection);
static void _dbus_connection_remove_timeout_locked (DBusConnection *connection,
DBusTimeout *timeout);
@ -572,8 +563,8 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
connection->pending_replies = pending_replies;
connection->filter_list = NULL;
connection->data_slots = NULL;
connection->n_slots = 0;
_dbus_data_slot_list_init (&connection->slot_list);
connection->client_serial = 1;
connection->disconnect_message_link = disconnect_link;
@ -798,8 +789,9 @@ _dbus_connection_last_unref (DBusConnection *connection)
_dbus_timeout_list_free (connection->timeouts);
connection->timeouts = NULL;
_dbus_connection_free_data_slots_nolock (connection);
/* calls out to application code... */
_dbus_data_slot_list_free (&connection->slot_list);
_dbus_hash_iter_init (connection->handler_table, &iter);
while (_dbus_hash_iter_next (&iter))
@ -1078,6 +1070,10 @@ reply_handler_data_free (ReplyHandlerData *data)
* you want a very short or very long timeout. There is no way to
* avoid a timeout entirely, other than passing INT_MAX for the
* timeout to postpone it indefinitely.
*
* @todo I think we should rename this function family
* dbus_connection_send(), send_with_reply(), etc. (i.e.
* drop the "message" part), the names are too long.
*
* @param connection the connection
* @param message the message to send
@ -1086,13 +1082,6 @@ reply_handler_data_free (ReplyHandlerData *data)
* @param result return location for result code
* @returns #TRUE if the message is successfully queued, #FALSE if no memory.
*
* @todo this function isn't implemented because we need message serials
* and other slightly more rich DBusMessage implementation in order to
* implement it. The basic idea will be to keep a hash of serials we're
* expecting a reply to, and also to add a way to tell GLib or Qt to
* install a timeout. Then install a timeout which is the shortest
* timeout of any pending reply.
*
*/
dbus_bool_t
dbus_connection_send_message_with_reply (DBusConnection *connection,
@ -1227,10 +1216,9 @@ dbus_connection_send_message_with_reply (DBusConnection *connection,
* wrong, result is set to whatever is appropriate, such as
* #DBUS_RESULT_NO_MEMORY.
*
* @todo I believe if we get EINTR or otherwise interrupt the
* do_iteration call in here, we won't block the required length of
* time. I think there probably has to be a loop: "while (!timeout_elapsed)
* { check_for_reply_in_queue(); iterate_with_remaining_timeout(); }"
* @todo could use performance improvements (it keeps scanning
* the whole message queue for example) and has thread issues,
* see comments in source
*
* @param connection the connection
* @param message the message to send
@ -1247,22 +1235,47 @@ dbus_connection_send_message_with_reply_and_block (DBusConnection *connectio
{
dbus_int32_t client_serial;
DBusList *link;
long start_tv_sec, start_tv_usec;
long end_tv_sec, end_tv_usec;
long tv_sec, tv_usec;
if (timeout_milliseconds == -1)
timeout_milliseconds = DEFAULT_TIMEOUT_VALUE;
/* it would probably seem logical to pass in _DBUS_INT_MAX
* for infinite timeout, but then math below would get
* all overflow-prone, so smack that down.
*/
if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
if (!dbus_connection_send_message (connection, message, &client_serial, result))
return NULL;
message = NULL;
/* Flush message queue */
dbus_connection_flush (connection);
dbus_mutex_lock (connection->mutex);
_dbus_get_current_time (&start_tv_sec, &start_tv_usec);
end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
_dbus_verbose ("will block %d milliseconds from %ld sec %ld usec to %ld sec %ld usec\n",
timeout_milliseconds,
start_tv_sec, start_tv_usec,
end_tv_sec, end_tv_usec);
/* Now we wait... */
/* THREAD TODO: This is busted. What if a dispatch_message or pop_message
* gets the message before we do?
*/
block_again:
_dbus_connection_do_iteration (connection,
DBUS_ITERATION_DO_READING |
DBUS_ITERATION_BLOCK,
@ -1278,7 +1291,7 @@ dbus_connection_send_message_with_reply_and_block (DBusConnection *connectio
if (_dbus_message_get_reply_serial (reply) == client_serial)
{
_dbus_list_remove (&connection->incoming_messages, link);
dbus_message_ref (message);
dbus_message_ref (reply);
if (result)
*result = DBUS_RESULT_SUCCESS;
@ -1289,8 +1302,27 @@ dbus_connection_send_message_with_reply_and_block (DBusConnection *connectio
link = _dbus_list_get_next_link (&connection->incoming_messages, link);
}
if (result)
*result = DBUS_RESULT_NO_REPLY;
_dbus_get_current_time (&tv_sec, &tv_usec);
if (tv_sec < start_tv_sec)
; /* clock set backward, bail out */
else if (connection->disconnect_message_link == NULL)
; /* we're disconnected, bail out */
else if (tv_sec < end_tv_sec ||
(tv_sec == end_tv_sec && tv_usec < end_tv_usec))
{
timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
(end_tv_usec - tv_usec) / 1000;
_dbus_verbose ("%d milliseconds remain\n", timeout_milliseconds);
_dbus_assert (timeout_milliseconds > 0);
goto block_again; /* not expired yet */
}
if (dbus_connection_get_is_connected (connection))
dbus_set_result (result, DBUS_RESULT_NO_REPLY);
else
dbus_set_result (result, DBUS_RESULT_DISCONNECTED);
dbus_mutex_unlock (connection->mutex);
@ -1850,6 +1882,12 @@ dbus_connection_remove_filter (DBusConnection *connection,
* this function with the name of a message that already has a
* handler. If the function returns #FALSE, the handlers were not
* registered due to lack of memory.
*
* @todo the messages_to_handle arg may be more convenient if it's a
* single string instead of an array. Though right now MessageHandler
* is sort of designed to say be associated with an entire object with
* multiple methods, that's why for example the connection only
* weakrefs it. So maybe the "manual" API should be different.
*
* @param connection the connection
* @param handler the handler
@ -1969,25 +2007,23 @@ dbus_connection_unregister_handler (DBusConnection *connection,
dbus_mutex_unlock (connection->mutex);
}
static int *allocated_slots = NULL;
static int n_allocated_slots = 0;
static int n_used_slots = 0;
static DBusMutex *allocated_slots_lock = NULL;
static DBusDataSlotAllocator slot_allocator;
/**
* Initialize the mutex used for #DBusConnecton data
* Initialize the mutex used for #DBusConnection data
* slot reservations.
*
* @returns the mutex
*/
DBusMutex *
_dbus_allocated_slots_init_lock (void)
_dbus_connection_slots_init_lock (void)
{
allocated_slots_lock = dbus_mutex_new ();
return allocated_slots_lock;
if (!_dbus_data_slot_allocator_init (&slot_allocator))
return NULL;
else
return slot_allocator.lock;
}
/**
* Allocates an integer ID to be used for storing application-specific
* data on any DBusConnection. The allocated ID may then be used
@ -2001,50 +2037,7 @@ _dbus_allocated_slots_init_lock (void)
int
dbus_connection_allocate_data_slot (void)
{
int slot;
if (!dbus_mutex_lock (allocated_slots_lock))
return -1;
if (n_used_slots < n_allocated_slots)
{
slot = 0;
while (slot < n_allocated_slots)
{
if (allocated_slots[slot] < 0)
{
allocated_slots[slot] = slot;
n_used_slots += 1;
break;
}
++slot;
}
_dbus_assert (slot < n_allocated_slots);
}
else
{
int *tmp;
slot = -1;
tmp = dbus_realloc (allocated_slots,
sizeof (int) * (n_allocated_slots + 1));
if (tmp == NULL)
goto out;
allocated_slots = tmp;
slot = n_allocated_slots;
n_allocated_slots += 1;
n_used_slots += 1;
allocated_slots[slot] = slot;
}
_dbus_assert (slot >= 0);
_dbus_assert (slot < n_allocated_slots);
out:
dbus_mutex_unlock (allocated_slots_lock);
return slot;
return _dbus_data_slot_allocator_alloc (&slot_allocator);
}
/**
@ -2061,22 +2054,7 @@ dbus_connection_allocate_data_slot (void)
void
dbus_connection_free_data_slot (int slot)
{
dbus_mutex_lock (allocated_slots_lock);
_dbus_assert (slot < n_allocated_slots);
_dbus_assert (allocated_slots[slot] == slot);
allocated_slots[slot] = -1;
n_used_slots -= 1;
if (n_used_slots == 0)
{
dbus_free (allocated_slots);
allocated_slots = NULL;
n_allocated_slots = 0;
}
dbus_mutex_unlock (allocated_slots_lock);
_dbus_data_slot_allocator_free (&slot_allocator, slot);
}
/**
@ -2100,50 +2078,25 @@ dbus_connection_set_data (DBusConnection *connection,
{
DBusFreeFunction old_free_func;
void *old_data;
dbus_bool_t retval;
dbus_mutex_lock (connection->mutex);
_dbus_assert (slot < n_allocated_slots);
_dbus_assert (allocated_slots[slot] == slot);
retval = _dbus_data_slot_list_set (&slot_allocator,
&connection->slot_list,
slot, data, free_data_func,
&old_free_func, &old_data);
if (slot >= connection->n_slots)
{
DBusDataSlot *tmp;
int i;
tmp = dbus_realloc (connection->data_slots,
sizeof (DBusDataSlot) * (slot + 1));
if (tmp == NULL)
{
dbus_mutex_unlock (connection->mutex);
return FALSE;
}
connection->data_slots = tmp;
i = connection->n_slots;
connection->n_slots = slot + 1;
while (i < connection->n_slots)
{
connection->data_slots[i].data = NULL;
connection->data_slots[i].free_data_func = NULL;
++i;
}
}
_dbus_assert (slot < connection->n_slots);
old_data = connection->data_slots[slot].data;
old_free_func = connection->data_slots[slot].free_data_func;
connection->data_slots[slot].data = data;
connection->data_slots[slot].free_data_func = free_data_func;
dbus_mutex_unlock (connection->mutex);
/* Do the actual free outside the connection lock */
if (old_free_func)
(* old_free_func) (old_data);
if (retval)
{
/* Do the actual free outside the connection lock */
if (old_free_func)
(* old_free_func) (old_data);
}
return TRUE;
return retval;
}
/**
@ -2161,15 +2114,11 @@ dbus_connection_get_data (DBusConnection *connection,
void *res;
dbus_mutex_lock (connection->mutex);
res = _dbus_data_slot_list_get (&slot_allocator,
&connection->slot_list,
slot);
_dbus_assert (slot < n_allocated_slots);
_dbus_assert (allocated_slots[slot] == slot);
if (slot >= connection->n_slots)
res = NULL;
else
res = connection->data_slots[slot].data;
dbus_mutex_unlock (connection->mutex);
return res;
@ -2187,30 +2136,6 @@ dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
_dbus_modify_sigpipe = will_modify_sigpipe;
}
/* This must be called with the connection lock not held to avoid
* holding it over the free_data callbacks, so it can basically
* only be called at last unref
*/
static void
_dbus_connection_free_data_slots_nolock (DBusConnection *connection)
{
int i;
i = 0;
while (i < connection->n_slots)
{
if (connection->data_slots[i].free_data_func)
(* connection->data_slots[i].free_data_func) (connection->data_slots[i].data);
connection->data_slots[i].data = NULL;
connection->data_slots[i].free_data_func = NULL;
++i;
}
dbus_free (connection->data_slots);
connection->data_slots = NULL;
connection->n_slots = 0;
}
/**
* Specifies the maximum size message this connection is allowed to
* receive. Larger messages will result in disconnecting the

372
dbus/dbus-dataslot.c Normal file
View file

@ -0,0 +1,372 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-dataslot.c storing data on objects
*
* Copyright (C) 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "dbus-dataslot.h"
#include "dbus-threads.h"
/**
* @defgroup DBusDataSlot Data slots
* @ingroup DBusInternals
* @brief Storing data by ID
*
* Types and functions related to storing data by an
* allocated ID. This is used for dbus_connection_set_data(),
* dbus_server_set_data(), etc.
* @{
*/
/**
* Initializes a data slot allocator object, used to assign
* integer IDs for data slots.
*
* @param allocator the allocator to initialize
*/
dbus_bool_t
_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator)
{
allocator->allocated_slots = NULL;
allocator->n_allocated_slots = 0;
allocator->n_used_slots = 0;
allocator->lock = dbus_mutex_new ();
if (allocator->lock == NULL)
return FALSE;
else
return TRUE;
}
/**
* Allocates an integer ID to be used for storing data
* in a #DBusDataSlotList.
*
* @param allocator the allocator
* @returns the integer ID, or -1 on failure
*/
int
_dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator)
{
int slot;
if (!dbus_mutex_lock (allocator->lock))
return -1;
if (allocator->n_used_slots < allocator->n_allocated_slots)
{
slot = 0;
while (slot < allocator->n_allocated_slots)
{
if (allocator->allocated_slots[slot] < 0)
{
allocator->allocated_slots[slot] = slot;
allocator->n_used_slots += 1;
break;
}
++slot;
}
_dbus_assert (slot < allocator->n_allocated_slots);
}
else
{
int *tmp;
slot = -1;
tmp = dbus_realloc (allocator->allocated_slots,
sizeof (int) * (allocator->n_allocated_slots + 1));
if (tmp == NULL)
goto out;
allocator->allocated_slots = tmp;
slot = allocator->n_allocated_slots;
allocator->n_allocated_slots += 1;
allocator->n_used_slots += 1;
allocator->allocated_slots[slot] = slot;
}
_dbus_assert (slot >= 0);
_dbus_assert (slot < allocator->n_allocated_slots);
out:
dbus_mutex_unlock (allocator->lock);
return slot;
}
/**
* Deallocates an ID previously allocated with
* _dbus_data_slot_allocator_alloc(). Existing data stored on
* existing #DBusDataList objects with this ID will be freed when the
* data list is finalized, but may not be retrieved (and may only be
* replaced if someone else reallocates the slot).
*
* @param allocator the allocator
* @param slot the slot to deallocate
*/
void
_dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
int slot)
{
dbus_mutex_lock (allocator->lock);
_dbus_assert (slot < allocator->n_allocated_slots);
_dbus_assert (allocator->allocated_slots[slot] == slot);
allocator->allocated_slots[slot] = -1;
allocator->n_used_slots -= 1;
if (allocator->n_used_slots == 0)
{
dbus_free (allocator->allocated_slots);
allocator->allocated_slots = NULL;
allocator->n_allocated_slots = 0;
}
dbus_mutex_unlock (allocator->lock);
}
/**
* Initializes a slot list.
* @param list the list to initialize.
*/
void
_dbus_data_slot_list_init (DBusDataSlotList *list)
{
list->slots = NULL;
list->n_slots = 0;
}
/**
* Stores a pointer in the data slot list, along with an optional
* function to be used for freeing the data when the data is set
* again, or when the slot list is finalized. The slot number must
* have been allocated with _dbus_data_slot_allocator_alloc() for the
* same allocator passed in here. The same allocator has to be used
* with the slot list every time.
*
* @param allocator the allocator to use
* @param list the data slot list
* @param slot the slot number
* @param data the data to store
* @param free_data_func finalizer function for the data
* @param old_free_func free function for any previously-existing data
* @param old_data previously-existing data, should be freed with old_free_func
* @returns #TRUE if there was enough memory to store the data
*/
dbus_bool_t
_dbus_data_slot_list_set (DBusDataSlotAllocator *allocator,
DBusDataSlotList *list,
int slot,
void *data,
DBusFreeFunction free_data_func,
DBusFreeFunction *old_free_func,
void **old_data)
{
_dbus_assert (slot < allocator->n_allocated_slots);
_dbus_assert (allocator->allocated_slots[slot] == slot);
if (slot >= list->n_slots)
{
DBusDataSlot *tmp;
int i;
tmp = dbus_realloc (list->slots,
sizeof (DBusDataSlot) * (slot + 1));
if (tmp == NULL)
return FALSE;
list->slots = tmp;
i = list->n_slots;
list->n_slots = slot + 1;
while (i < list->n_slots)
{
list->slots[i].data = NULL;
list->slots[i].free_data_func = NULL;
++i;
}
}
_dbus_assert (slot < list->n_slots);
*old_data = list->slots[slot].data;
*old_free_func = list->slots[slot].free_data_func;
list->slots[slot].data = data;
list->slots[slot].free_data_func = free_data_func;
return TRUE;
}
/**
* Retrieves data previously set with _dbus_data_slot_list_set_data().
* The slot must still be allocated (must not have been freed).
*
* @param allocator the allocator slot was allocated from
* @param list the data slot list
* @param slot the slot to get data from
* @returns the data, or #NULL if not found
*/
void*
_dbus_data_slot_list_get (DBusDataSlotAllocator *allocator,
DBusDataSlotList *list,
int slot)
{
_dbus_assert (slot < allocator->n_allocated_slots);
_dbus_assert (allocator->allocated_slots[slot] == slot);
if (slot >= list->n_slots)
return NULL;
else
return list->slots[slot].data;
}
/**
* Frees the data slot list and all data slots contained
* in it, calling application-provided free functions
* if they exist.
*
* @param list the list to free
*/
void
_dbus_data_slot_list_free (DBusDataSlotList *list)
{
int i;
i = 0;
while (i < list->n_slots)
{
if (list->slots[i].free_data_func)
(* list->slots[i].free_data_func) (list->slots[i].data);
list->slots[i].data = NULL;
list->slots[i].free_data_func = NULL;
++i;
}
dbus_free (list->slots);
list->slots = NULL;
list->n_slots = 0;
}
/** @} */
#ifdef DBUS_BUILD_TESTS
#include "dbus-test.h"
#include <stdio.h>
static int free_counter;
static void
test_free_slot_data_func (void *data)
{
int i = _DBUS_POINTER_TO_INT (data);
_dbus_assert (free_counter == i);
++free_counter;
}
/**
* Test function for data slots
*/
dbus_bool_t
_dbus_data_slot_test (void)
{
DBusDataSlotAllocator allocator;
DBusDataSlotList list;
int i;
DBusFreeFunction old_free_func;
void *old_data;
if (!_dbus_data_slot_allocator_init (&allocator))
_dbus_assert_not_reached ("no memory for allocator");
_dbus_data_slot_list_init (&list);
#define N_SLOTS 100
i = 0;
while (i < N_SLOTS)
{
/* we don't really want apps to rely on this ordered
* allocation, but it simplifies things to rely on it
* here.
*/
if (_dbus_data_slot_allocator_alloc (&allocator) != i)
_dbus_assert_not_reached ("did not allocate slots in numeric order\n");
++i;
}
i = 0;
while (i < N_SLOTS)
{
if (!_dbus_data_slot_list_set (&allocator, &list,
i,
_DBUS_INT_TO_POINTER (i),
test_free_slot_data_func,
&old_free_func, &old_data))
_dbus_assert_not_reached ("no memory to set data");
_dbus_assert (old_free_func == NULL);
_dbus_assert (old_data == NULL);
_dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) ==
_DBUS_INT_TO_POINTER (i));
++i;
}
free_counter = 0;
i = 0;
while (i < N_SLOTS)
{
if (!_dbus_data_slot_list_set (&allocator, &list,
i,
_DBUS_INT_TO_POINTER (i),
test_free_slot_data_func,
&old_free_func, &old_data))
_dbus_assert_not_reached ("no memory to set data");
_dbus_assert (old_free_func == test_free_slot_data_func);
_dbus_assert (_DBUS_POINTER_TO_INT (old_data) == i);
(* old_free_func) (old_data);
_dbus_assert (i == (free_counter - 1));
_dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) ==
_DBUS_INT_TO_POINTER (i));
++i;
}
free_counter = 0;
_dbus_data_slot_list_free (&list);
_dbus_assert (N_SLOTS == free_counter);
i = 0;
while (i < N_SLOTS)
{
_dbus_data_slot_allocator_free (&allocator, i);
++i;
}
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */

76
dbus/dbus-dataslot.h Normal file
View file

@ -0,0 +1,76 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-dataslot.h storing data on objects
*
* Copyright (C) 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef DBUS_DATASLOT_H
#define DBUS_DATASLOT_H
#include <dbus/dbus-internals.h>
DBUS_BEGIN_DECLS;
typedef struct DBusDataSlotAllocator DBusDataSlotAllocator;
typedef struct DBusDataSlotList DBusDataSlotList;
/** Opaque typedef for DBusDataSlot */
typedef struct DBusDataSlot DBusDataSlot;
/** DBusDataSlot is used to store application data on the connection */
struct DBusDataSlot
{
void *data; /**< The application data */
DBusFreeFunction free_data_func; /**< Free the application data */
};
struct DBusDataSlotAllocator
{
int *allocated_slots; /**< Allocated slots */
int n_allocated_slots; /**< number of slots malloc'd */
int n_used_slots; /**< number of slots used */
DBusMutex *lock; /**< thread lock */
};
struct DBusDataSlotList
{
DBusDataSlot *slots; /**< Data slots */
int n_slots; /**< Slots we have storage for in data_slots */
};
dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator);
int _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator);
void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
int slot_id);
void _dbus_data_slot_list_init (DBusDataSlotList *list);
dbus_bool_t _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator,
DBusDataSlotList *list,
int slot,
void *data,
DBusFreeFunction free_data_func,
DBusFreeFunction *old_free_func,
void **old_data);
void* _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator,
DBusDataSlotList *list,
int slot);
void _dbus_data_slot_list_free (DBusDataSlotList *list);
DBUS_END_DECLS;
#endif /* DBUS_DATASLOT_H */

View file

@ -118,6 +118,8 @@ char* _dbus_strdup (const char *str);
#define _DBUS_MAX_SUN_PATH_LENGTH 99
#define _DBUS_ONE_KILOBYTE 1024
#define _DBUS_ONE_MEGABYTE 1024 * _DBUS_ONE_KILOBYTE
#define _DBUS_ONE_HOUR_IN_MILLISECONDS (1000 * 60 * 60)
#define _DBUS_USEC_PER_SECOND (1000000)
#undef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
@ -155,12 +157,12 @@ dbus_bool_t _dbus_decrement_fail_alloc_counter (void);
#endif /* !DBUS_BUILD_TESTS */
/* Thread initializers */
DBusMutex *_dbus_list_init_lock (void);
DBusMutex *_dbus_allocated_slots_init_lock (void);
DBusMutex *_dbus_atomic_init_lock (void);
DBusMutex *_dbus_message_handler_init_lock (void);
DBusMutex *_dbus_user_info_init_lock (void);
DBusMutex *_dbus_list_init_lock (void);
DBusMutex *_dbus_connection_slots_init_lock (void);
DBusMutex *_dbus_server_slots_init_lock (void);
DBusMutex *_dbus_atomic_init_lock (void);
DBusMutex *_dbus_message_handler_init_lock (void);
DBusMutex *_dbus_user_info_init_lock (void);
DBUS_END_DECLS;

View file

@ -168,7 +168,7 @@ free_keys (DBusKey *keys,
*/
/** Maximum number of timeouts waiting for lock before we decide it's stale */
#define MAX_LOCK_TIMEOUTS 16
#define MAX_LOCK_TIMEOUTS 32
/** Length of each timeout while waiting for a lock */
#define LOCK_TIMEOUT_MILLISECONDS 250

View file

@ -184,8 +184,12 @@ get_string_field (DBusMessage *message,
int field,
int *len)
{
int offset = message->header_fields[field].offset;
int offset;
const char *data;
offset = message->header_fields[field].offset;
_dbus_assert (field < FIELD_LAST);
if (offset < 0)
return NULL;
@ -209,13 +213,17 @@ get_string_field (DBusMessage *message,
static dbus_int32_t
get_int_field (DBusMessage *message,
int field)
int field)
{
int offset = message->header_fields[field].offset;
int offset;
_dbus_assert (field < FIELD_LAST);
offset = message->header_fields[field].offset;
if (offset < 0)
return -1; /* useless if -1 is a valid value of course */
return _dbus_demarshal_int32 (&message->header,
message->byte_order,
offset,
@ -798,8 +806,8 @@ dbus_message_new_reply (DBusMessage *original_message)
FIELD_SENDER, NULL);
name = get_string_field (original_message,
FIELD_NAME, NULL);
_dbus_assert (sender != NULL);
/* sender is allowed to be null here in peer-to-peer case */
message = dbus_message_new (sender, name);
@ -1703,6 +1711,10 @@ dbus_message_get_args_valist (DBusMessage *message,
* ref/unref is kind of annoying to deal with, and slower too.
* This implies not ref'ing the message from the iter.
*
* @todo I'd also name this dbus_message_iter_new() or
* for the static object dbus_message_iter_init() rather
* than making it a method on the message
*
* @param message the message
* @returns a new iter.
*/

View file

@ -28,6 +28,7 @@
#include <dbus/dbus-timeout.h>
#include <dbus/dbus-watch.h>
#include <dbus/dbus-resources.h>
#include <dbus/dbus-dataslot.h>
DBUS_BEGIN_DECLS;
@ -61,6 +62,8 @@ struct DBusServer
*/
int max_connections; /**< Max number of connections allowed at once. */
DBusDataSlotList slot_list; /**< Data stored by allocated integer ID */
DBusNewConnectionFunction new_connection_function;
/**< Callback to invoke when a new connection is created. */

View file

@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-server.c DBusServer object
*
* Copyright (C) 2002 Red Hat Inc.
* Copyright (C) 2002, 2003 Red Hat Inc.
*
* Licensed under the Academic Free License version 1.2
*
@ -37,6 +37,9 @@
* A DBusServer represents a server that other applications
* can connect to. Each connection from another application
* is represented by a DBusConnection.
*
* @todo Thread safety hasn't been looked at for #DBusServer
* @todo Need notification to apps of disconnection, may matter for some transports
*/
/**
@ -86,6 +89,8 @@ _dbus_server_init_base (DBusServer *server,
}
server->max_connections = 256; /* same as an X server, seems like a nice default */
_dbus_data_slot_list_init (&server->slot_list);
return TRUE;
}
@ -99,6 +104,9 @@ _dbus_server_init_base (DBusServer *server,
void
_dbus_server_finalize_base (DBusServer *server)
{
/* calls out to application code... */
_dbus_data_slot_list_free (&server->slot_list);
dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
if (!server->disconnected)
@ -510,5 +518,131 @@ dbus_server_get_n_connections (DBusServer *server)
return _dbus_counter_get_value (server->connection_counter);
}
static DBusDataSlotAllocator slot_allocator;
/**
* Initialize the mutex used for #DBusConnection data
* slot reservations.
*
* @returns the mutex
*/
DBusMutex *
_dbus_server_slots_init_lock (void)
{
if (!_dbus_data_slot_allocator_init (&slot_allocator))
return NULL;
else
return slot_allocator.lock;
}
/**
* Allocates an integer ID to be used for storing application-specific
* data on any DBusServer. The allocated ID may then be used
* with dbus_server_set_data() and dbus_server_get_data().
* If allocation fails, -1 is returned. Again, the allocated
* slot is global, i.e. all DBusServer objects will
* have a slot with the given integer ID reserved.
*
* @returns -1 on failure, otherwise the data slot ID
*/
int
dbus_server_allocate_data_slot (void)
{
return _dbus_data_slot_allocator_alloc (&slot_allocator);
}
/**
* Deallocates a global ID for server data slots.
* dbus_server_get_data() and dbus_server_set_data()
* may no longer be used with this slot.
* Existing data stored on existing DBusServer objects
* will be freed when the server is finalized,
* but may not be retrieved (and may only be replaced
* if someone else reallocates the slot).
*
* @param slot the slot to deallocate
*/
void
dbus_server_free_data_slot (int slot)
{
_dbus_data_slot_allocator_free (&slot_allocator, slot);
}
/**
* Stores a pointer on a DBusServer, along
* with an optional function to be used for freeing
* the data when the data is set again, or when
* the server is finalized. The slot number
* must have been allocated with dbus_server_allocate_data_slot().
*
* @param server the server
* @param slot the slot number
* @param data the data to store
* @param free_data_func finalizer function for the data
* @returns #TRUE if there was enough memory to store the data
*/
dbus_bool_t
dbus_server_set_data (DBusServer *server,
int slot,
void *data,
DBusFreeFunction free_data_func)
{
DBusFreeFunction old_free_func;
void *old_data;
dbus_bool_t retval;
#if 0
dbus_mutex_lock (server->mutex);
#endif
retval = _dbus_data_slot_list_set (&slot_allocator,
&server->slot_list,
slot, data, free_data_func,
&old_free_func, &old_data);
#if 0
dbus_mutex_unlock (server->mutex);
#endif
if (retval)
{
/* Do the actual free outside the server lock */
if (old_free_func)
(* old_free_func) (old_data);
}
return retval;
}
/**
* Retrieves data previously set with dbus_server_set_data().
* The slot must still be allocated (must not have been freed).
*
* @param server the server
* @param slot the slot to get data from
* @returns the data, or #NULL if not found
*/
void*
dbus_server_get_data (DBusServer *server,
int slot)
{
void *res;
#if 0
dbus_mutex_lock (server->mutex);
#endif
res = _dbus_data_slot_list_get (&slot_allocator,
&server->slot_list,
slot);
#if 0
dbus_mutex_unlock (server->mutex);
#endif
return res;
}
/** @} */

View file

@ -71,6 +71,15 @@ int dbus_server_get_max_connections (DBusServer *server)
int dbus_server_get_n_connections (DBusServer *server);
int dbus_server_allocate_data_slot (void);
void dbus_server_free_data_slot (int slot);
dbus_bool_t dbus_server_set_data (DBusServer *server,
int slot,
void *data,
DBusFreeFunction free_data_func);
void* dbus_server_get_data (DBusServer *server,
int slot);
DBUS_END_DECLS;
#endif /* DBUS_SERVER_H */

View file

@ -59,6 +59,10 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir)
if (!_dbus_string_test ())
die ("strings");
printf ("%s: running data slot tests\n", "dbus-test");
if (!_dbus_data_slot_test ())
die ("dataslot");
printf ("%s: running keyring tests\n", "dbus-test");
if (!_dbus_keyring_test ())
die ("keyring");

View file

@ -35,17 +35,18 @@ typedef enum
_DBUS_MESSAGE_UNKNOWN
} DBusMessageValidity;
dbus_bool_t _dbus_hash_test (void);
dbus_bool_t _dbus_list_test (void);
dbus_bool_t _dbus_marshal_test (void);
dbus_bool_t _dbus_mem_pool_test (void);
dbus_bool_t _dbus_string_test (void);
dbus_bool_t _dbus_address_test (void);
dbus_bool_t _dbus_message_test (const char *test_data_dir);
dbus_bool_t _dbus_auth_test (const char *test_data_dir);
dbus_bool_t _dbus_md5_test (void);
dbus_bool_t _dbus_sha_test (const char *test_data_dir);
dbus_bool_t _dbus_keyring_test (void);
dbus_bool_t _dbus_hash_test (void);
dbus_bool_t _dbus_list_test (void);
dbus_bool_t _dbus_marshal_test (void);
dbus_bool_t _dbus_mem_pool_test (void);
dbus_bool_t _dbus_string_test (void);
dbus_bool_t _dbus_address_test (void);
dbus_bool_t _dbus_message_test (const char *test_data_dir);
dbus_bool_t _dbus_auth_test (const char *test_data_dir);
dbus_bool_t _dbus_md5_test (void);
dbus_bool_t _dbus_sha_test (const char *test_data_dir);
dbus_bool_t _dbus_keyring_test (void);
dbus_bool_t _dbus_data_slot_test (void);
void dbus_internal_do_not_use_run_tests (const char *test_data_dir);
dbus_bool_t dbus_internal_do_not_use_try_message_file (const DBusString *filename,

View file

@ -205,7 +205,8 @@ init_static_locks(void)
DBusMutex *mutex;
} static_locks[] = {
{&_dbus_list_init_lock},
{&_dbus_allocated_slots_init_lock},
{&_dbus_server_slots_init_lock},
{&_dbus_connection_slots_init_lock},
{&_dbus_atomic_init_lock},
{&_dbus_message_handler_init_lock},
{&_dbus_user_info_init_lock}

View file

@ -157,7 +157,12 @@ check_write_watch (DBusTransport *transport)
_dbus_watch_unref (unix_transport->write_watch);
unix_transport->write_watch = NULL;
}
else
{
_dbus_verbose ("Write watch is unchanged from %p on fd %d\n",
unix_transport->write_watch, unix_transport->fd);
}
out:
_dbus_transport_unref (transport);
}
@ -173,9 +178,16 @@ check_read_watch (DBusTransport *transport)
_dbus_transport_ref (transport);
need_read_watch =
_dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size;
if (_dbus_transport_get_is_authenticated (transport))
need_read_watch =
_dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size;
else
need_read_watch = transport->receive_credentials_pending ||
_dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_WAITING_FOR_INPUT;
_dbus_verbose ("need_read_watch = %d authenticated = %d\n",
need_read_watch, _dbus_transport_get_is_authenticated (transport));
if (transport->disconnected)
need_read_watch = FALSE;
@ -213,7 +225,12 @@ check_read_watch (DBusTransport *transport)
_dbus_watch_unref (unix_transport->read_watch);
unix_transport->read_watch = NULL;
}
else
{
_dbus_verbose ("Read watch is unchanged from %p on fd %d\n",
unix_transport->read_watch, unix_transport->fd);
}
out:
_dbus_transport_unref (transport);
}
@ -552,6 +569,7 @@ do_authentication (DBusTransport *transport,
}
out:
check_read_watch (transport);
check_write_watch (transport);
_dbus_transport_unref (transport);
}
@ -902,10 +920,12 @@ unix_do_iteration (DBusTransport *transport,
dbus_bool_t do_select;
int select_res;
_dbus_verbose (" iteration flags = %s%s timeout = %d\n",
_dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p\n",
flags & DBUS_ITERATION_DO_READING ? "read" : "",
flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
timeout_milliseconds);
timeout_milliseconds,
unix_transport->read_watch,
unix_transport->write_watch);
/* "again" has to be up here because on EINTR the fd sets become
* undefined
@ -948,13 +968,15 @@ unix_do_iteration (DBusTransport *transport,
auth_state = _dbus_auth_do_work (transport->auth);
if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
if (transport->receive_credentials_pending ||
auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
{
FD_SET (unix_transport->fd, &read_set);
do_select = TRUE;
}
if (auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
if (transport->send_credentials_pending ||
auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
{
FD_SET (unix_transport->fd, &write_set);
do_select = TRUE;

View file

@ -485,6 +485,9 @@ _dbus_transport_do_iteration (DBusTransport *transport,
{
_dbus_assert (transport->vtable->do_iteration != NULL);
_dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
flags, timeout_milliseconds, !transport->disconnected);
if ((flags & (DBUS_ITERATION_DO_WRITING |
DBUS_ITERATION_DO_READING)) == 0)
return; /* Nothing to do */

View file

@ -26,7 +26,8 @@
#include <dbus/dbus.h>
#include <glib.h>
void dbus_gthread_init (void);
void dbus_connection_hookup_with_g_main (DBusConnection *connection);
void dbus_gthread_init (void);
void dbus_connection_setup_with_g_main (DBusConnection *connection);
void dbus_server_setup_with_g_main (DBusServer *server);
#endif /* DBUS_GLIB_H */

View file

@ -24,40 +24,77 @@
#include "dbus-glib.h"
#include <glib.h>
typedef struct _DBusGSource DBusGSource;
/**
* @defgroup DBusGLib GLib bindings
* @ingroup DBus
* @brief API for using D-BUS with GLib
*
* Convenience functions are provided for using D-BUS
* with the GLib library (see http://www.gtk.org for GLib
* information).
*
*/
struct _DBusGSource
/**
* @defgroup DBusGLibInternals GLib bindings implementation details
* @ingroup DBusInternals
* @brief Implementation details of GLib bindings
*
* @{
*/
/** @typedef DBusGSource
* A GSource representing a #DBusConnection or #DBusServer
*/
typedef struct DBusGSource DBusGSource;
struct DBusGSource
{
GSource source;
GSource source; /**< the parent GSource */
DBusConnection *connection;
GList *poll_fds; /**< descriptors we're watching */
GHashTable *watches; /**< hash of DBusWatch objects */
GList *poll_fds;
GHashTable *watches;
void *connection_or_server; /**< DBusConnection or DBusServer */
};
static GStaticMutex connection_slot_lock = G_STATIC_MUTEX_INIT;
static int connection_slot = -1;
static GStaticMutex server_slot_lock = G_STATIC_MUTEX_INIT;
static int server_slot = -1;
static gboolean dbus_connection_prepare (GSource *source,
gint *timeout);
gint *timeout);
static gboolean dbus_connection_check (GSource *source);
static gboolean dbus_connection_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data);
GSourceFunc callback,
gpointer user_data);
static gboolean dbus_server_prepare (GSource *source,
gint *timeout);
static gboolean dbus_server_check (GSource *source);
static gboolean dbus_server_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data);
static GSourceFuncs dbus_funcs = {
static GSourceFuncs dbus_connection_funcs = {
dbus_connection_prepare,
dbus_connection_check,
dbus_connection_dispatch,
NULL
};
static GSourceFuncs dbus_server_funcs = {
dbus_server_prepare,
dbus_server_check,
dbus_server_dispatch,
NULL
};
static gboolean
dbus_connection_prepare (GSource *source,
gint *timeout)
{
DBusConnection *connection = ((DBusGSource *)source)->connection;
DBusConnection *connection = ((DBusGSource *)source)->connection_or_server;
*timeout = -1;
@ -65,7 +102,16 @@ dbus_connection_prepare (GSource *source,
}
static gboolean
dbus_connection_check (GSource *source)
dbus_server_prepare (GSource *source,
gint *timeout)
{
*timeout = -1;
return FALSE;
}
static gboolean
dbus_gsource_check (GSource *source)
{
DBusGSource *dbus_source = (DBusGSource *)source;
GList *list;
@ -86,9 +132,22 @@ dbus_connection_check (GSource *source)
}
static gboolean
dbus_connection_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
dbus_connection_check (GSource *source)
{
return dbus_gsource_check (source);
}
static gboolean
dbus_server_check (GSource *source)
{
return dbus_gsource_check (source);
}
static gboolean
dbus_gsource_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data,
dbus_bool_t is_server)
{
DBusGSource *dbus_source = (DBusGSource *)source;
GList *copy, *list;
@ -115,21 +174,63 @@ dbus_connection_dispatch (GSource *source,
condition |= DBUS_WATCH_ERROR;
if (poll_fd->revents & G_IO_HUP)
condition |= DBUS_WATCH_HANGUP;
dbus_connection_handle_watch (dbus_source->connection, watch, condition);
if (is_server)
dbus_server_handle_watch (dbus_source->connection_or_server,
watch, condition);
else
dbus_connection_handle_watch (dbus_source->connection_or_server,
watch, condition);
}
list = list->next;
}
g_list_free (copy);
/* Dispatch messages */
while (dbus_connection_dispatch_message (dbus_source->connection));
g_list_free (copy);
return TRUE;
}
static gboolean
dbus_connection_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
DBusGSource *dbus_source = (DBusGSource *)source;
DBusConnection *connection = dbus_source->connection_or_server;
dbus_connection_ref (connection);
dbus_gsource_dispatch (source, callback, user_data,
FALSE);
/* Dispatch messages */
while (dbus_connection_dispatch_message (connection))
;
dbus_connection_unref (connection);
return TRUE;
}
static gboolean
dbus_server_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
DBusGSource *dbus_source = (DBusGSource *)source;
DBusServer *server = dbus_source->connection_or_server;
dbus_server_ref (server);
dbus_gsource_dispatch (source, callback, user_data,
TRUE);
dbus_server_unref (server);
return TRUE;
}
static void
add_watch (DBusWatch *watch,
gpointer data)
@ -184,7 +285,6 @@ timeout_handler (gpointer data)
return FALSE;
}
static void
add_timeout (DBusTimeout *timeout,
void *data)
@ -204,7 +304,7 @@ remove_timeout (DBusTimeout *timeout,
guint timeout_tag;
timeout_tag = GPOINTER_TO_UINT (dbus_timeout_get_data (timeout));
g_source_remove (timeout_tag);
}
@ -214,33 +314,112 @@ free_source (GSource *source)
g_source_destroy (source);
}
void
dbus_connection_hookup_with_g_main (DBusConnection *connection)
/** @} */ /* End of GLib bindings internals */
/** @addtogroup DBusGLib
* @{
*/
static GSource*
create_source (void *connection_or_server,
GSourceFuncs *funcs)
{
GSource *source;
DBusGSource *dbus_source;
source = g_source_new (&dbus_funcs, sizeof (DBusGSource));
source = g_source_new (funcs, sizeof (DBusGSource));
dbus_source = (DBusGSource *)source;
dbus_source->watches = g_hash_table_new (NULL, NULL);
dbus_source->connection = connection;
dbus_source->connection_or_server = connection_or_server;
return source;
}
/**
* Sets the watch and timeout functions of a #DBusConnection
* to integrate the connection with the GLib main loop.
*
* @param connection the connection
*/
void
dbus_connection_setup_with_g_main (DBusConnection *connection)
{
GSource *source;
source = create_source (connection, &dbus_connection_funcs);
dbus_connection_set_watch_functions (connection,
add_watch,
remove_watch,
source, NULL);
dbus_connection_set_timeout_functions (connection,
add_timeout,
remove_timeout,
NULL, NULL);
add_watch,
remove_watch,
source, NULL);
dbus_connection_set_timeout_functions (connection,
add_timeout,
remove_timeout,
NULL, NULL);
g_source_attach (source, NULL);
g_static_mutex_lock (&connection_slot_lock);
if (connection_slot == -1 )
connection_slot = dbus_connection_allocate_data_slot ();
g_static_mutex_unlock (&connection_slot_lock);
dbus_connection_set_data (connection, connection_slot, source,
(DBusFreeFunction)free_source);
if (connection_slot < 0)
goto nomem;
if (!dbus_connection_set_data (connection, connection_slot, source,
(DBusFreeFunction)free_source))
goto nomem;
return;
nomem:
g_error ("Not enough memory to set up DBusConnection for use with GLib");
}
/**
* Sets the watch and timeout functions of a #DBusServer
* to integrate the server with the GLib main loop.
*
* @param server the server
*/
void
dbus_server_setup_with_g_main (DBusServer *server)
{
GSource *source;
source = create_source (server, &dbus_server_funcs);
dbus_server_set_watch_functions (server,
add_watch,
remove_watch,
source, NULL);
dbus_server_set_timeout_functions (server,
add_timeout,
remove_timeout,
NULL, NULL);
g_source_attach (source, NULL);
g_static_mutex_lock (&server_slot_lock);
if (server_slot == -1 )
server_slot = dbus_server_allocate_data_slot ();
g_static_mutex_unlock (&server_slot_lock);
if (server_slot < 0)
goto nomem;
if (!dbus_server_set_data (server, server_slot, source,
(DBusFreeFunction)free_source))
goto nomem;
return;
nomem:
g_error ("Not enough memory to set up DBusServer for use with GLib");
}
/** @} */ /* end of public API */

View file

@ -25,6 +25,10 @@
#include <dbus/dbus.h>
#include "dbus-glib.h"
/** @addtogroup DBusGLibInternals
* @{
*/
static DBusMutex * dbus_gmutex_new (void);
static void dbus_gmutex_free (DBusMutex *mutex);
static dbus_bool_t dbus_gmutex_lock (DBusMutex *mutex);
@ -149,7 +153,17 @@ dbus_gcondvar_wake_all (DBusCondVar *cond)
g_cond_broadcast ((GCond *)cond);
}
/** @} End of internals */
/** @addtogroup DBusGLib
* @{
*/
/**
* Initializes the D-BUS thread system to use
* GLib threads. This function may only be called
* once and must be called prior to calling any
* other function in the D-BUS API.
*/
void
dbus_gthread_init (void)
{
@ -158,3 +172,5 @@ dbus_gthread_init (void)
dbus_threads_init (&functions);
}
/** @} end of public API */

View file

@ -27,7 +27,7 @@ main (int argc, char **argv)
return 1;
}
dbus_connection_hookup_with_g_main (connection);
dbus_connection_setup_with_g_main (connection);
message = dbus_message_new ("org.freedesktop.DBus", "org.freedesktop.DBus.Hello");