コード例 #1
0
ファイル: camel-object-bag.c プロジェクト: Pecisk/eds-gtasks
/**
 * camel_object_bag_add:
 * @bag: a #CamelObjectBag
 * @key: a reserved key
 * @object: a #GObject
 *
 * Adds @object to @bag.  The @key MUST have been previously reserved using
 * camel_object_bag_reserve().
 **/
void
camel_object_bag_add (CamelObjectBag *bag,
                      gconstpointer key,
                      gpointer object)
{
	g_return_if_fail (bag != NULL);
	g_return_if_fail (key != NULL);
	g_return_if_fail (G_IS_OBJECT (object));

	g_mutex_lock (&bag->mutex);

	/* Check it's the *same* object, not an old one at the same address */
	if (!object_in_bag (bag, object)) {
		ObjRef *ref;
		gpointer copied_key;

		ref = g_slice_new (ObjRef);
		ref->bag = bag;
		/* We need to stash a 'raw' pointer since that's the key we use
		 * in the key_table */
		ref->obj = object;
		g_weak_ref_init (&ref->ref, object);
		copied_key = bag->key_copy_func (key);
		g_hash_table_insert (bag->key_table, object, copied_key);
		g_hash_table_insert (bag->object_table, copied_key, ref);
		object_bag_unreserve (bag, key);

		g_object_weak_ref (
			G_OBJECT (object),
			(GWeakNotify) object_bag_notify, bag);
	}

	g_mutex_unlock (&bag->mutex);
}
コード例 #2
0
ファイル: camel-object-bag.c プロジェクト: Pecisk/eds-gtasks
/**
 * camel_object_bag_get:
 * @bag: a #CamelObjectBag
 * @key: a key
 *
 * Lookup an object by @key.  If the key is currently reserved, the function
 * will block until another thread commits or aborts the reservation.  The
 * caller owns the reference to the returned object.  Use g_object_unref ()
 * to unreference it.
 *
 * Returns: the object corresponding to @key, or %NULL if not found
 **/
gpointer
camel_object_bag_get (CamelObjectBag *bag,
                      gconstpointer key)
{
	KeyReservation *reservation;
	ObjRef *ref;
	gpointer object = NULL;

	g_return_val_if_fail (bag != NULL, NULL);
	g_return_val_if_fail (key != NULL, NULL);

	g_mutex_lock (&bag->mutex);

	/* Look for the key in the bag. */
	ref = g_hash_table_lookup (bag->object_table, key);
	if (ref != NULL) {
		object = g_weak_ref_get (&ref->ref);
		if (object != NULL) {
			g_mutex_unlock (&bag->mutex);
			return object;
		}

		/* Remove stale reference to dead object. */
		g_hash_table_remove (bag->key_table, ref->obj);
		g_hash_table_remove (bag->object_table, key);
	}

	/* Check if the key has been reserved. */
	reservation = key_reservation_lookup (bag, key);
	if (reservation == NULL) {
		/* No such key, so return NULL. */
		g_mutex_unlock (&bag->mutex);
		return NULL;
	}

	/* Wait for the key to be unreserved. */
	reservation->waiters++;
	while (reservation->owner != NULL)
		g_cond_wait (&reservation->cond, &bag->mutex);
	reservation->waiters--;

	/* Check if an object was added by another thread. */
	ref = g_hash_table_lookup (bag->object_table, key);
	if (ref != NULL) {
		object = g_weak_ref_get (&ref->ref);
		if (object == NULL) {
			/* Remove stale reference to dead object. */
			g_hash_table_remove (bag->key_table, ref->obj);
			g_hash_table_remove (bag->object_table, key);
		}
	}

	/* We're not reserving it. */
	reservation->owner = g_thread_self ();
	object_bag_unreserve (bag, key);

	g_mutex_unlock (&bag->mutex);

	return object;
}
コード例 #3
0
ファイル: camel-object-bag.c プロジェクト: Pecisk/eds-gtasks
/**
 * camel_object_bag_reserve:
 * @bag: a #CamelObjectBag
 * @key: the key to reserve
 *
 * Reserves @key in @bag.  If @key is already reserved in another thread,
 * then wait until the reservation has been committed.
 *
 * After reserving @key, you either get a reference to the object
 * corresponding to @key (similar to camel_object_bag_get()) or you get
 * %NULL, signifying that you MUST call either camel_object_bag_add() or
 * camel_object_bag_abort().
 *
 * Returns: the object for @key, or %NULL if @key is not found
 **/
gpointer
camel_object_bag_reserve (CamelObjectBag *bag,
                          gconstpointer key)
{
	KeyReservation *reservation;
	ObjRef *ref;
	gpointer object = NULL;

	g_return_val_if_fail (bag != NULL, NULL);
	g_return_val_if_fail (key != NULL, NULL);

	g_mutex_lock (&bag->mutex);

	/* If object for key already exists, return it immediately. */
	ref = g_hash_table_lookup (bag->object_table, key);
	if (ref != NULL) {
		object = g_weak_ref_get (&ref->ref);
		if (object != NULL) {
			g_mutex_unlock (&bag->mutex);
			return object;
		}

		/* Remove stale reference to dead object. */
		g_hash_table_remove (bag->key_table, ref->obj);
		g_hash_table_remove (bag->object_table, key);
	}

	/* If no such key exists in the bag, create a reservation. */
	reservation = key_reservation_lookup (bag, key);
	if (reservation == NULL) {
		key_reservation_new (bag, key);
		g_mutex_unlock (&bag->mutex);
		return NULL;
	}

	/* Wait for the reservation to be committed or aborted. */
	reservation->waiters++;
	while (reservation->owner != NULL)
		g_cond_wait (&reservation->cond, &bag->mutex);
	reservation->owner = g_thread_self ();
	reservation->waiters--;

	/* Check if the object was added by another thread. */
	ref = g_hash_table_lookup (bag->object_table, key);
	if (ref != NULL) {
		object = g_weak_ref_get (&ref->ref);
		if (object != NULL) {
			/* We have an object; no need to reserve the key. */
			object_bag_unreserve (bag, key);
		} else {
			/* Remove stale reference to dead object. */
			g_hash_table_remove (bag->key_table, ref->obj);
			g_hash_table_remove (bag->object_table, key);
		}
	}

	g_mutex_unlock (&bag->mutex);

	return object;
}
コード例 #4
0
/**
 * camel_object_bag_add:
 * @bag: a #CamelObjectBag
 * @key: a reserved key
 * @object: a #GObject
 *
 * Adds @object to @bag.  The @key MUST have been previously reserved using
 * camel_object_bag_reserve().
 **/
void
camel_object_bag_add (CamelObjectBag *bag,
                      gconstpointer key,
                      gpointer object)
{
	g_return_if_fail (bag != NULL);
	g_return_if_fail (key != NULL);
	g_return_if_fail (G_IS_OBJECT (object));

	g_mutex_lock (bag->mutex);

	if (g_hash_table_lookup (bag->key_table, object) == NULL) {
		gpointer copied_key;

		copied_key = bag->key_copy_func (key);
		g_hash_table_insert (bag->key_table, object, copied_key);
		g_hash_table_insert (bag->object_table, copied_key, object);
		object_bag_unreserve (bag, key);

		g_object_weak_ref (
			G_OBJECT (object), (GWeakNotify)
			object_bag_notify, bag);
	}

	g_mutex_unlock (bag->mutex);
}
コード例 #5
0
ファイル: camel-object-bag.c プロジェクト: Pecisk/eds-gtasks
/**
 * camel_object_bag_abort:
 * @bag: a #CamelObjectBag
 * @key: a reserved key
 *
 * Aborts a key reservation.
 **/
void
camel_object_bag_abort (CamelObjectBag *bag,
                        gconstpointer key)
{
	g_return_if_fail (bag != NULL);
	g_return_if_fail (key != NULL);

	g_mutex_lock (&bag->mutex);

	object_bag_unreserve (bag, key);

	g_mutex_unlock (&bag->mutex);
}