diff options
-rw-r--r-- | camel/ChangeLog | 11 | ||||
-rw-r--r-- | camel/camel-data-cache.c | 17 | ||||
-rw-r--r-- | camel/camel-object.c | 64 |
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) { |