diff --git a/lib/cmap.c b/lib/cmap.c index db2b4a4f091..44c899125d7 100644 --- a/lib/cmap.c +++ b/lib/cmap.c @@ -654,8 +654,10 @@ cmap_try_insert(struct cmap_impl *impl, struct cmap_node *node, uint32_t hash) /* Inserts 'node', with the given 'hash', into 'cmap'. The caller must ensure * that 'cmap' cannot change concurrently (from another thread). If duplicates * are undesirable, the caller must have already verified that 'cmap' does not - * contain a duplicate of 'node'. */ -void + * contain a duplicate of 'node'. + * + * Returns the current number of nodes in the cmap after the insertion. */ +size_t cmap_insert(struct cmap *cmap, struct cmap_node *node, uint32_t hash) { struct cmap_impl *impl = cmap_get_impl(cmap); @@ -669,7 +671,7 @@ cmap_insert(struct cmap *cmap, struct cmap_node *node, uint32_t hash) while (OVS_UNLIKELY(!cmap_try_insert(impl, node, hash))) { impl = cmap_rehash(cmap, impl->mask); } - impl->n++; + return ++impl->n; } static bool @@ -705,28 +707,17 @@ cmap_replace__(struct cmap_impl *impl, struct cmap_node *node, } } -/* Removes 'node' from 'cmap'. The caller must ensure that 'cmap' cannot - * change concurrently (from another thread). - * - * 'node' must not be destroyed or modified or inserted back into 'cmap' or - * into any other concurrent hash map while any other thread might be accessing - * it. One correct way to do this is to free it from an RCU callback with - * ovsrcu_postpone(). */ -void -cmap_remove(struct cmap *cmap, struct cmap_node *node, uint32_t hash) -{ - cmap_replace(cmap, node, NULL, hash); - cmap_get_impl(cmap)->n--; -} - /* Replaces 'old_node' in 'cmap' with 'new_node'. The caller must * ensure that 'cmap' cannot change concurrently (from another thread). * * 'old_node' must not be destroyed or modified or inserted back into 'cmap' or * into any other concurrent hash map while any other thread might be accessing * it. One correct way to do this is to free it from an RCU callback with - * ovsrcu_postpone(). */ -void + * ovsrcu_postpone(). + * + * Returns the current number of nodes in the cmap after the replacement. The + * number of nodes decreases by one if 'new_node' is NULL. */ +size_t cmap_replace(struct cmap *cmap, struct cmap_node *old_node, struct cmap_node *new_node, uint32_t hash) { @@ -738,6 +729,11 @@ cmap_replace(struct cmap *cmap, struct cmap_node *old_node, ok = cmap_replace__(impl, old_node, new_node, hash, h1) || cmap_replace__(impl, old_node, new_node, hash, h2); ovs_assert(ok); + + if (!new_node) { + impl->n--; + } + return impl->n; } static bool diff --git a/lib/cmap.h b/lib/cmap.h index 793202de663..4783be3000a 100644 --- a/lib/cmap.h +++ b/lib/cmap.h @@ -87,11 +87,12 @@ void cmap_destroy(struct cmap *); size_t cmap_count(const struct cmap *); bool cmap_is_empty(const struct cmap *); -/* Insertion and deletion. */ -void cmap_insert(struct cmap *, struct cmap_node *, uint32_t hash); -void cmap_remove(struct cmap *, struct cmap_node *, uint32_t hash); -void cmap_replace(struct cmap *, struct cmap_node *old_node, - struct cmap_node *new_node, uint32_t hash); +/* Insertion and deletion. Return the current count after the operation. */ +size_t cmap_insert(struct cmap *, struct cmap_node *, uint32_t hash); +static inline size_t cmap_remove(struct cmap *, struct cmap_node *, + uint32_t hash); +size_t cmap_replace(struct cmap *, struct cmap_node *old_node, + struct cmap_node *new_node, uint32_t hash); /* Search. * @@ -225,4 +226,19 @@ cmap_first(const struct cmap *cmap) return cmap_next_position(cmap, &pos); } +/* Removes 'node' from 'cmap'. The caller must ensure that 'cmap' cannot + * change concurrently (from another thread). + * + * 'node' must not be destroyed or modified or inserted back into 'cmap' or + * into any other concurrent hash map while any other thread might be accessing + * it. One correct way to do this is to free it from an RCU callback with + * ovsrcu_postpone(). + * + * Returns the current number of nodes in the cmap after the removal. */ +static inline size_t +cmap_remove(struct cmap *cmap, struct cmap_node *node, uint32_t hash) +{ + return cmap_replace(cmap, node, NULL, hash); +} + #endif /* cmap.h */