Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #159282

Re: container_of macro...

From "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Newsgroups comp.lang.c
Subject Re: container_of macro...
Date 2021-03-10 17:13 -0800
Organization Aioe.org NNTP Server
Message-ID <s2bqsf$1bsi$1@gioia.aioe.org> (permalink)
References <s26io0$nne$1@gioia.aioe.org> <20210309075236.629@kylheku.com> <874khk6xhg.fsf@bsb.me.uk> <20210309093722.442@kylheku.com>

Show all headers | View raw


On 3/9/2021 9:51 AM, Kaz Kylheku wrote:
> On 2021-03-09, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
>> Kaz Kylheku <563-365-8930@kylheku.com> writes:
>>
>>> On 2021-03-09, Chris M. Thomasson <chris.m.thomasson.1@gmail.com> wrote:
>>>> How many people here use it?
>>>
>>> If you put the contained structure as the first member, you don't need
>>> this; just a straight cast.
>>
>> But you then can't write generic list algorithms, no?
> 
> The intrusive container approach for generic containers, though it has
> some nice characteristics with regard to memory allocation, is very
> limited.
> 
> Firstly, by its very nature, it is incompatible with functional
> programming. Objects must be mutated in order to put them into a list.
> 
> Secondly, once an object is on a list, it cannot be simultaneously put
> into another list. (Unless, of course, it has more list nodes, which
> is where we run into container_of).
> 
> The "object on one list at a time" has basically one text book use case:
> the OS scheduler. A process in some state, one state at a time. States
> have queues associated with them, and so a process moves between
> different queues. For that, it can have links built into it, and so
> no allocation takes place.
> 
> This is not a "generic container" situation though.
> 
>>> That takes care of probably more than the proverbial 95% of the
>>> situations.
>>
>> Maybe such generic code is all in the 5%.  I would argue percentages if
>> that's what you are saying.
> 
> If I needed a generic container with multiple intrusive node links
> today, I would spend the bytes and put the numeric offset into the link
> node structure.
> 
> The offsetof macro is error prone. If a structure has several list
> nodes:
> 
>   struct foo {
>      lnode_t anode;
>      lnode_t bnode;
>      lnode_t cnode;
>   }
> 
> If we have a pointer ptr, to say, the cnode, but we accidentally do
> this:
> 
>     container_of(ptr, struct foo, bnode)
> 
> we have a critical error: the returned pointer is wrong; it points
> somewhere before the structure.

Big time! The programmer needs to be very careful, indeed. But then 
again, this is C.

> 
> If node has an offset to the parent structure, we can have a different
> inline function or macro for that, just:
> 
>     container_of(ptr, struct foo)
> 
> this retrieves ptr->offset, subtracts it from the char * version of ptr,
> and casts it to struct foo *.

Well, please excuse my ignorance here, but are you suggesting that a 
node store its offset to its containing structure? Humm... That might 
not be okay on space constrained systems?


> 
> That also allows us to write generic code (which we should be concerned
> with if our motivation is "generic containers"). We can write a single
> common function which takes a pointer to any list node, whether it be
> the object's anode, bnode or cathode (EE joke, sorry) and easily
> converts it to the struct foo *, to then operate on that object.
> 
> We correctly initialize ptr->offset in one place.
> 
> We could have a ptr->parent poiner instead, but ptr->offset has
> the virtue of being relative. If we assign one initialized structure
> to another, the offsets work correctly in the copied structure,
> whereas back-pointers will not:
> 
>    *pfooa = *pfoob;
> 
> Offsets can be packed into smaller fields though. E.g. on 64 bit,
> we burn 8 bytes for a parent pointer, but there could be situations
> in which a smaller type could be used for an offset to some
> advantage, alignment of surroundings permitting.
> 

Back to comp.lang.c | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

container_of macro... "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-03-08 17:24 -0800
  Re: container_of macro... Öö Tiib <ootiib@hot.ee> - 2021-03-09 02:06 -0800
    Re: container_of macro... "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-03-10 17:02 -0800
  Re: container_of macro... Kaz Kylheku <563-365-8930@kylheku.com> - 2021-03-09 15:59 +0000
    Re: container_of macro... Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-03-09 17:35 +0000
      Re: container_of macro... Kaz Kylheku <563-365-8930@kylheku.com> - 2021-03-09 17:51 +0000
        Re: container_of macro... "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-03-10 17:13 -0800
    Re: container_of macro... "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-03-10 17:05 -0800
  Re: container_of macro... William Ahern <william@25thandClement.com> - 2021-03-09 18:56 -0800
    Re: container_of macro... Kaz Kylheku <563-365-8930@kylheku.com> - 2021-03-10 03:47 +0000
      Re: container_of macro... William Ahern <william@25thandClement.com> - 2021-03-12 17:01 -0800
        Re: container_of macro... Jim <jim.cromie@gmail.com> - 2021-03-16 22:14 -0700
    Re: container_of macro... "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-03-10 17:07 -0800

csiph-web