aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog11
-rw-r--r--camel/camel-data-cache.c17
-rw-r--r--camel/camel-object.c64
3 files changed, 81 insertions, 11 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index e22217db0e..c864e4cadf 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,14 @@
+2004-01-21 Not Zed <NotZed@Ximian.com>
+
+ ** See bug #52996.
+
+ * camel-data-cache.c (camel_data_cache_add): put a do-loop around
+ the object_bag_reserve stuff, otherwise we can add/abort out of
+ sync (i.e. when object_bag_reserve returned a pointer we mustn't
+ call add/abort).
+
+ * camel-object.c (camel_object_bag_*): Added some inline doco.
+
2004-01-20 Not Zed <NotZed@Ximian.com>
** See bug #52817.
diff --git a/camel/camel-data-cache.c b/camel/camel-data-cache.c
index a585f59a9d..3a2586e3a9 100644
--- a/camel/camel-data-cache.c
+++ b/camel/camel-data-cache.c
@@ -287,12 +287,17 @@ camel_data_cache_add(CamelDataCache *cdc, const char *path, const char *key, Cam
CamelStream *stream;
real = data_cache_path(cdc, TRUE, path, key);
- stream = camel_object_bag_reserve(cdc->priv->busy_bag, real);
- if (stream) {
- unlink(real);
- camel_object_bag_remove(cdc->priv->busy_bag, stream);
- camel_object_unref(stream);
- }
+ /* need to loop 'cause otherwise we can call bag_add/bag_abort
+ * after bag_reserve returned a pointer, which is an invalid
+ * sequence. */
+ do {
+ stream = camel_object_bag_reserve(cdc->priv->busy_bag, real);
+ if (stream) {
+ unlink(real);
+ camel_object_bag_remove(cdc->priv->busy_bag, stream);
+ camel_object_unref(stream);
+ }
+ } while (stream != NULL);
stream = camel_stream_fs_new_with_name(real, O_RDWR|O_CREAT|O_TRUNC, 0600);
if (stream)
diff --git a/camel/camel-object.c b/camel/camel-object.c
index 43ff9c1d7f..a87c2de8b6 100644
--- a/camel/camel-object.c
+++ b/camel/camel-object.c
@@ -1618,6 +1618,19 @@ camel_object_class_dump_tree(CamelType root)
object_class_dump_tree_rec(root, 0);
}
+/**
+ * camel_object_bag_new:
+ * @hash:
+ * @equal:
+ * @keycopy:
+ * @keyfree:
+ *
+ * Allocate a new object bag. Object bag's are key'd hash tables of
+ * camel-objects which can be updated atomically using transaction
+ * semantics.
+ *
+ * Return value:
+ **/
CamelObjectBag *
camel_object_bag_new (GHashFunc hash, GEqualFunc equal, CamelCopyFunc keycopy, GFreeFunc keyfree)
{
@@ -1689,6 +1702,15 @@ co_bag_unreserve(CamelObjectBag *bag, const void *key)
}
}
+/**
+ * camel_object_bag_add:
+ * @bag:
+ * @key:
+ * @vo:
+ *
+ * Add an object @vo to the object bag @bag. The @key MUST have
+ * previously been reserved using camel_object_bag_reserve().
+ **/
void
camel_object_bag_add (CamelObjectBag *bag, const void *key, void *vo)
{
@@ -1729,6 +1751,18 @@ camel_object_bag_add (CamelObjectBag *bag, const void *key, void *vo)
camel_object_unget_hooks(o);
}
+/**
+ * camel_object_bag_get:
+ * @bag:
+ * @key:
+ *
+ * Lookup an object by @key. If the key is currently reserved, then
+ * wait until the key has been committed before continuing.
+ *
+ * Return value: NULL if the object corresponding to @key is not
+ * in the bag. Otherwise a ref'd object pointer which the caller owns
+ * the ref to.
+ **/
void *
camel_object_bag_get (CamelObjectBag *bag, const void *key)
{
@@ -1774,10 +1808,24 @@ camel_object_bag_get (CamelObjectBag *bag, const void *key)
return o;
}
-/* like get, but also reserve a spot for key if it isn't there */
-/* After calling reserve, you MUST call bag_abort or bag_add */
-/* Also note that currently you can only reserve a single key
- at any one time in a given thread */
+/**
+ * camel_object_bag_reserve:
+ * @bag:
+ * @key:
+ *
+ * Reserve a key in the object bag. If the key is already reserved in
+ * another thread, then wait until the reservation has been committed.
+ *
+ * After reserving a key, you either get a reffed pointer to the
+ * object corresponding to the key, similar to object_bag_get, or you
+ * get NULL, signifying that you then MIST call either object_bag_add
+ * or object_bag_abort.
+ *
+ * You may reserve multiple keys from the same thread, but they should
+ * always be reserved in the same order, to avoid deadlocks.
+ *
+ * Return value:
+ **/
void *
camel_object_bag_reserve (CamelObjectBag *bag, const void *key)
{
@@ -1832,7 +1880,13 @@ camel_object_bag_reserve (CamelObjectBag *bag, const void *key)
return o;
}
-/* abort a reserved key */
+/**
+ * camel_object_bag_abort:
+ * @bag:
+ * @key:
+ *
+ * Abort a key reservation.
+ **/
void
camel_object_bag_abort (CamelObjectBag *bag, const void *key)
{