diff mbox series

[5/5] cbtree.h: define cb_init() in terms of CBTREE_INIT

Message ID patch-5.5-7e571667674-20210927T003330Z-avarab@gmail.com (mailing list archive)
State Superseded
Headers show
Series Designated initializer cleanup & conversion | expand

Commit Message

Ævar Arnfjörð Bjarmason Sept. 27, 2021, 12:39 a.m. UTC
Use the same pattern for cb_init() as the one established in the
recent refactoring of other such patterns in
5726a6b4012 (*.c *_init(): define in terms of corresponding *_INIT
macro, 2021-07-01).

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 cbtree.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Comments

Johannes Sixt Sept. 27, 2021, 6:37 a.m. UTC | #1
Am 27.09.21 um 02:39 schrieb Ævar Arnfjörð Bjarmason:
> --- a/cbtree.h
> +++ b/cbtree.h
> @@ -37,11 +37,12 @@ enum cb_next {
>  	CB_BREAK = 1
>  };
>  
> -#define CBTREE_INIT { .root = NULL }
> +#define CBTREE_INIT { 0 }
>  
>  static inline void cb_init(struct cb_tree *t)
>  {
> -	t->root = NULL;
> +	struct cb_tree blank = CBTREE_INIT;

This could be

	static const struct cb_tree blank = CBTREE_INIT;

> +	memcpy(t, &blank, sizeof(*t));

Is
	*t = blank;

not a thing in C?

-- Hannes
Phillip Wood Sept. 27, 2021, 9:13 a.m. UTC | #2
Hi Ævar

On 27/09/2021 01:39, Ævar Arnfjörð Bjarmason wrote:
> Use the same pattern for cb_init() as the one established in the
> recent refactoring of other such patterns in
> 5726a6b4012 (*.c *_init(): define in terms of corresponding *_INIT
> macro, 2021-07-01).
> 
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>   cbtree.h | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/cbtree.h b/cbtree.h
> index a04a312c3f5..dedbb8e2a45 100644
> --- a/cbtree.h
> +++ b/cbtree.h
> @@ -37,11 +37,12 @@ enum cb_next {
>   	CB_BREAK = 1
>   };
>   
> -#define CBTREE_INIT { .root = NULL }
> +#define CBTREE_INIT { 0 }
>   
>   static inline void cb_init(struct cb_tree *t)
>   {
> -	t->root = NULL;
> +	struct cb_tree blank = CBTREE_INIT;
> +	memcpy(t, &blank, sizeof(*t));
>   }

Slightly off topic but would this be a good site for a compound literal 
test balloon?

	*t = (struct cb_tree){ 0 };

Compound literals are in C99 and seem to have been supported by MSVC 
since 2013 [1].

Best Wishes

Phillip

[1] 
https://docs.microsoft.com/en-us/cpp/porting/visual-cpp-what-s-new-2003-through-2015?view=msvc-160#whats-new-for-c-in-visual-studio-2013

>   struct cb_node *cb_lookup(struct cb_tree *, const uint8_t *k, size_t klen);
>
Ævar Arnfjörð Bjarmason Sept. 27, 2021, 11 a.m. UTC | #3
On Mon, Sep 27 2021, Phillip Wood wrote:

> Hi Ævar
>
> On 27/09/2021 01:39, Ævar Arnfjörð Bjarmason wrote:
>> Use the same pattern for cb_init() as the one established in the
>> recent refactoring of other such patterns in
>> 5726a6b4012 (*.c *_init(): define in terms of corresponding *_INIT
>> macro, 2021-07-01).
>> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>> ---
>>   cbtree.h | 5 +++--
>>   1 file changed, 3 insertions(+), 2 deletions(-)
>> diff --git a/cbtree.h b/cbtree.h
>> index a04a312c3f5..dedbb8e2a45 100644
>> --- a/cbtree.h
>> +++ b/cbtree.h
>> @@ -37,11 +37,12 @@ enum cb_next {
>>   	CB_BREAK = 1
>>   };
>>   -#define CBTREE_INIT { .root = NULL }
>> +#define CBTREE_INIT { 0 }
>>     static inline void cb_init(struct cb_tree *t)
>>   {
>> -	t->root = NULL;
>> +	struct cb_tree blank = CBTREE_INIT;
>> +	memcpy(t, &blank, sizeof(*t));
>>   }
>
> Slightly off topic but would this be a good site for a compound
> literal test balloon?
>
> 	*t = (struct cb_tree){ 0 };
>
> Compound literals are in C99 and seem to have been supported by MSVC
> since 2013 [1].

I think that's a good thing to test out, FWIW I've also tested it on the
IBM xlc, Oracle SunCC and HP/UX's aCC, they all seem to accept it.

But I'd prefer just doing that in some general follow-up to bd4232fac33
(Merge branch 'ab/struct-init', 2021-07-16), i.e. let's just use the
init pattern it established here.
Ævar Arnfjörð Bjarmason Sept. 27, 2021, 11:02 a.m. UTC | #4
On Mon, Sep 27 2021, Johannes Sixt wrote:

> Am 27.09.21 um 02:39 schrieb Ævar Arnfjörð Bjarmason:
>> --- a/cbtree.h
>> +++ b/cbtree.h
>> @@ -37,11 +37,12 @@ enum cb_next {
>>  	CB_BREAK = 1
>>  };
>>  
>> -#define CBTREE_INIT { .root = NULL }
>> +#define CBTREE_INIT { 0 }
>>  
>>  static inline void cb_init(struct cb_tree *t)
>>  {
>> -	t->root = NULL;
>> +	struct cb_tree blank = CBTREE_INIT;
>
> This could be
>
> 	static const struct cb_tree blank = CBTREE_INIT;

*nod*...

>> +	memcpy(t, &blank, sizeof(*t));
>
> Is
> 	*t = blank;
>
> not a thing in C?
>
> -- Hannes

...but to both this & the above my reply in the side-thread at
https://lore.kernel.org/git/87h7e61duk.fsf@evledraar.gmail.com/
applies. I.e. this is just following a pattern I got from Jeff King &
used in bd4232fac33 (Merge branch 'ab/struct-init', 2021-07-16).

FWIW with "const" in general I don't use it as much as I'd personally
prefer, see e.g. [1] for one recent discussion, but maybe there wouldn't
be any push-back in this case...

1. https://lore.kernel.org/git/patch-1.1-c317e6e125e-20210921T124416Z-avarab@gmail.com/
Jeff King Sept. 27, 2021, 11:54 p.m. UTC | #5
On Mon, Sep 27, 2021 at 01:02:35PM +0200, Ævar Arnfjörð Bjarmason wrote:

> >>  static inline void cb_init(struct cb_tree *t)
> >>  {
> >> -	t->root = NULL;
> >> +	struct cb_tree blank = CBTREE_INIT;
> >
> > This could be
> >
> > 	static const struct cb_tree blank = CBTREE_INIT;
> 
> *nod*...
> [...]
> ...but to both this & the above my reply in the side-thread at
> https://lore.kernel.org/git/87h7e61duk.fsf@evledraar.gmail.com/
> applies. I.e. this is just following a pattern I got from Jeff King &
> used in bd4232fac33 (Merge branch 'ab/struct-init', 2021-07-16).

I'm not sure how a compiler would react to the "static const" thing. I
tested the compiler output for the "auto" struct case you've written
here, and at least gcc and clang are smart enough to just initialize the
pointed-to struct directly, with no extra copy.

For a "static const" I'm not sure if they'd end up with the same code,
or if they'd allocate a struct in the data segment and just memcpy()
into place. A non-const static would perhaps push it in the direction of the
data/memcpy thing, though the compiler should be well aware that the
struct is never changed nor aliased, and thus we're always writing the
INIT values.

I suspect the performance is not that different either way (the big
thing to avoid is initializing an auto struct on the fly and then
copying from it, but this is a pretty easy optimization for compilers to
get right).

> >> +	memcpy(t, &blank, sizeof(*t));
> >
> > Is
> > 	*t = blank;
> >
> > not a thing in C?

It would be fine to use struct assignment here, and should be equivalent
in most compilers. They know about memcpy() and will inline it as
appropriate.

I think some C programmers tend to prefer memcpy() just because that's
how they think. It also wasn't legal in old K&R compilers, but as far as
I know was in C89.

You have to take care with assignment of flex-structs, of course, but
you also have to do so with memcpy(), too. :)

> FWIW with "const" in general I don't use it as much as I'd personally
> prefer, see e.g. [1] for one recent discussion, but maybe there wouldn't
> be any push-back in this case...

This isn't a parameter, so I don't think that discussion applies. _If_
you are going to make it a static, I think a const makes sense here (but
probably does nothing beyond signaling your intention, because the
compiler can see that it is never modified), but I wouldn't bother with
either.

-Peff
Johannes Sixt Sept. 28, 2021, 6:15 a.m. UTC | #6
Am 28.09.21 um 01:54 schrieb Jeff King:
> On Mon, Sep 27, 2021 at 01:02:35PM +0200, Ævar Arnfjörð Bjarmason wrote:
> 
>>>>  static inline void cb_init(struct cb_tree *t)
>>>>  {
>>>> -	t->root = NULL;
>>>> +	struct cb_tree blank = CBTREE_INIT;
>>>
>>> This could be
>>>
>>> 	static const struct cb_tree blank = CBTREE_INIT;
>>
>> *nod*...
>> [...]
>> ...but to both this & the above my reply in the side-thread at
>> https://lore.kernel.org/git/87h7e61duk.fsf@evledraar.gmail.com/
>> applies. I.e. this is just following a pattern I got from Jeff King &
>> used in bd4232fac33 (Merge branch 'ab/struct-init', 2021-07-16).
> 
> I'm not sure how a compiler would react to the "static const" thing. I
> tested the compiler output for the "auto" struct case you've written
> here, and at least gcc and clang are smart enough to just initialize the
> pointed-to struct directly, with no extra copy.

Good! Then a deviation from established patterns is not warranted.

-- Hannes
Junio C Hamano Sept. 28, 2021, 6:32 p.m. UTC | #7
Jeff King <peff@peff.net> writes:

>> >> +	memcpy(t, &blank, sizeof(*t));
>> >
>> > Is
>> > 	*t = blank;
>> >
>> > not a thing in C?
>
> It would be fine to use struct assignment here, and should be equivalent
> in most compilers. They know about memcpy() and will inline it as
> appropriate.

FWIW, I'd be fine with structure assignment, but we already have too
many such memcpy(<ptr>, &<struct>, sizeof(struct)), adding one more
is not giving us too much incremental burden for later clean-up.

> I think some C programmers tend to prefer memcpy() just because that's
> how they think. It also wasn't legal in old K&R compilers, but as far as
> I know was in C89.

I think so, too.
Ævar Arnfjörð Bjarmason Sept. 28, 2021, 7:42 p.m. UTC | #8
On Tue, Sep 28 2021, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
>
>>> >> +	memcpy(t, &blank, sizeof(*t));
>>> >
>>> > Is
>>> > 	*t = blank;
>>> >
>>> > not a thing in C?
>>
>> It would be fine to use struct assignment here, and should be equivalent
>> in most compilers. They know about memcpy() and will inline it as
>> appropriate.
>
> FWIW, I'd be fine with structure assignment, but we already have too
> many such memcpy(<ptr>, &<struct>, sizeof(struct)), adding one more
> is not giving us too much incremental burden for later clean-up.
>
>> I think some C programmers tend to prefer memcpy() just because that's
>> how they think. It also wasn't legal in old K&R compilers, but as far as
>> I know was in C89.
>
> I think so, too.

Getting back to the topic of this v2 in general, my reading of the
discussion since then is that nothing in it necessitated a v3 re-roll to
address outstanding issues. If I've got that wrong please shout...
Junio C Hamano Sept. 28, 2021, 8:50 p.m. UTC | #9
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> On Tue, Sep 28 2021, Junio C Hamano wrote:
>
>> Jeff King <peff@peff.net> writes:
>>
>>>> >> +	memcpy(t, &blank, sizeof(*t));
>>>> >
>>>> > Is
>>>> > 	*t = blank;
>>>> >
>>>> > not a thing in C?
>>>
>>> It would be fine to use struct assignment here, and should be equivalent
>>> in most compilers. They know about memcpy() and will inline it as
>>> appropriate.
>>
>> FWIW, I'd be fine with structure assignment, but we already have too
>> many such memcpy(<ptr>, &<struct>, sizeof(struct)), adding one more
>> is not giving us too much incremental burden for later clean-up.
>>
>>> I think some C programmers tend to prefer memcpy() just because that's
>>> how they think. It also wasn't legal in old K&R compilers, but as far as
>>> I know was in C89.
>>
>> I think so, too.
>
> Getting back to the topic of this v2 in general, my reading of the
> discussion since then is that nothing in it necessitated a v3 re-roll to
> address outstanding issues. If I've got that wrong please shout...

I was hoping that these can hit 'next' soonish.
Phillip Wood Sept. 30, 2021, 10:01 a.m. UTC | #10
On 27/09/2021 12:00, Ævar Arnfjörð Bjarmason wrote:
> 
> On Mon, Sep 27 2021, Phillip Wood wrote:
> 
>> Hi Ævar
>>
>> On 27/09/2021 01:39, Ævar Arnfjörð Bjarmason wrote:
>>> Use the same pattern for cb_init() as the one established in the
>>> recent refactoring of other such patterns in
>>> 5726a6b4012 (*.c *_init(): define in terms of corresponding *_INIT
>>> macro, 2021-07-01).
>>> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>>> ---
>>>    cbtree.h | 5 +++--
>>>    1 file changed, 3 insertions(+), 2 deletions(-)
>>> diff --git a/cbtree.h b/cbtree.h
>>> index a04a312c3f5..dedbb8e2a45 100644
>>> --- a/cbtree.h
>>> +++ b/cbtree.h
>>> @@ -37,11 +37,12 @@ enum cb_next {
>>>    	CB_BREAK = 1
>>>    };
>>>    -#define CBTREE_INIT { .root = NULL }
>>> +#define CBTREE_INIT { 0 }
>>>      static inline void cb_init(struct cb_tree *t)
>>>    {
>>> -	t->root = NULL;
>>> +	struct cb_tree blank = CBTREE_INIT;
>>> +	memcpy(t, &blank, sizeof(*t));
>>>    }
>>
>> Slightly off topic but would this be a good site for a compound
>> literal test balloon?
>>
>> 	*t = (struct cb_tree){ 0 };
>>
>> Compound literals are in C99 and seem to have been supported by MSVC
>> since 2013 [1].
> 
> I think that's a good thing to test out, FWIW I've also tested it on the
> IBM xlc, Oracle SunCC and HP/UX's aCC, they all seem to accept it.

Thanks for taking the time to test those other systems, it's good to 
know they support compound literals

> But I'd prefer just doing that in some general follow-up to bd4232fac33
> (Merge branch 'ab/struct-init', 2021-07-16), i.e. let's just use the
> init pattern it established here.

I agree it makes sense to introduce it as a separate series. I'm not 
sure if there is a pressing need for them but it is the sort of thing 
that is occasionally useful.

Best Wishes

Phillip
diff mbox series

Patch

diff --git a/cbtree.h b/cbtree.h
index a04a312c3f5..dedbb8e2a45 100644
--- a/cbtree.h
+++ b/cbtree.h
@@ -37,11 +37,12 @@  enum cb_next {
 	CB_BREAK = 1
 };
 
-#define CBTREE_INIT { .root = NULL }
+#define CBTREE_INIT { 0 }
 
 static inline void cb_init(struct cb_tree *t)
 {
-	t->root = NULL;
+	struct cb_tree blank = CBTREE_INIT;
+	memcpy(t, &blank, sizeof(*t));
 }
 
 struct cb_node *cb_lookup(struct cb_tree *, const uint8_t *k, size_t klen);