git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 2/2] oidmap: rework iterators to return typed pointer

From
Jeff King <peff@peff.net>
Date
Apr 8, 2020, 22:08 UTC
Message-ID
<20200408220840.GB3468797@coredump.intra.peff.net>
In-Reply-To
<20200408070346.24872-2-abhishekkumar8222@gmail.com>
On Wed, Apr 08, 2020 at 12:33:46PM +0530, Abhishek Kumar wrote:
Show 9 quoted lines
> 87571c3f (hashmap: use *_entry APIs for iteration, 2019-10-06) modified
> hashmap_iter_next() to return a hashmap_entry pointer instead of void
> pointer.
> 
> However, oidmap_iter_next() is unaware of the struct type containing
> oidmap_entry and explicitly returns a void pointer.
> 
> Rework oidmap_iter_next() to include struct type and return appropriate
> pointer. This allows for compile-time type checks.

Yes, I think returning a pointer to an oidmap_entry makes sense. And then we get type safety, and anybody who wants embed an oidmap_entry can use container_of() to get back to their original struct.

But...
Show 8 quoted lines
> +/*
> + * Returns the next entry, or NULL if there are no more entries.
> + *
> + * The entry is of @type (e.g. "struct foo") and has a member of type struct
> + * oidmap_entry.
> + */
> +#define oidmap_iter_next(iter, type) \
> +	(type *) hashmap_iter_next(&(iter)->h_iter)

This cast is turning a hashmap_entry into whatever type the caller passed in. But it's doing it with a straight cast. We know that hashmap_entry and oidmap_entry pointers are equivalent, but we don't know where the oidmap_entry is with respect to the user's type.

I think oidmap_iter_next() should continue to be a function that returns an oidmap_entry pointer (and use container_of_or_null() to get to it from the hashmap_entry, even though we know the offset is 0).

And then the caller can either use container_of() to get to their original struct, or we can provide a helper macro. See the difference between hashmap_iter_first() and hashmap_iter_first_entry().

There's no hashmap_iter_next_entry(). There could be, but instead it skipped straight to hashmap_for_each_entry(), which uses an offset within the variable rather than the type. But likewise, we could add oidmap_for_each_entry() here.

Show 11 quoted lines
> diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c
> index 0acf99931e..a28bf007a8 100644
> --- a/t/helper/test-oidmap.c
> +++ b/t/helper/test-oidmap.c
> @@ -96,7 +96,7 @@ int cmd__oidmap(int argc, const char **argv)
>  
>  			struct oidmap_iter iter;
>  			oidmap_iter_init(&map, &iter);
> -			while ((entry = oidmap_iter_next(&iter)))
> +			while ((entry = oidmap_iter_next(&iter, struct test_entry)))
>  				printf("%s %s\n", oid_to_hex(&entry->entry.oid), entry->name);
This works because "test_entry" has the oidmap_entry at the start.

But it wouldn't work with a struct where that wasn't the case, nor would it provide any compile-time safety (because of the cast).

Note that if we do want to support that and get type safety (and I think it is worth doing), oidmap_get() would need similar treatment (it returns a void pointer, but it is really a pointer to an oidmap_entry). And I guess oidmap_put() and oidmap_remove(), which returns pointers to existing entries.

-Peff
Previous: Abhishek KumarNext: Jeff King
Message 6 of 10 in “oidmap: make oidmap_free independent of struct layout”
  1. 1/2 oidmap: make oidmap_free independent of struct layoutAbhishek Kumar, Apr 8, 2020
  2. 2/2 oidmap: rework iterators to return typed pointerAbhishek Kumar, Apr 8, 2020
  3. Junio C HamanoApr 8, 2020
  4. 1/2 oidmap: make oidmap_free independent of struct layoutAbhishek Kumar, Apr 8, 2020
  5. 2/2 oidmap: rework iterators to return typed pointerAbhishek Kumar, Apr 8, 2020
  6. Jeff KingApr 8, 2020
  7. Jeff KingApr 8, 2020
  8. 1/3 oidmap: make oidmap_free independent of struct layoutAbhishek Kumar, Apr 25, 2020
  9. 2/3 oidmap: rework iterators to return typed pointerAbhishek Kumar, Apr 25, 2020
  10. 3/3 oidmap: return oidmap_entry pointersAbhishek Kumar, Apr 25, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.