My proposal paper has a use case that can't be solved via base members (for intrusive lists, where an object can be in more than one list at once).

On Wed, Aug 31, 2022 at 11:36 PM Lénárd Szolnoki via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Hi,

I also like the proposal, but keep in mind that you can already do this if your subobject is a base member instead of a non-static data member of the complete object. I don't know if this would be applicable for your use case though, this proposal does add some flexibility that is not there with base members.

Cheers,
Lénárd

On 1 September 2022 05:35:13 BST, Lewis Baker via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
I also ran into another use-case that I have for P2300-related optimisations that I'd like to implement.

In my case, I am exploring whether it's possible to avoid child operation_state objects from needing to store the receiver
if the child operation_state object is a sub-object of a parent operation_state object and the receiver simply contains
a pointer to the parent operation_state (a very common situation).

In this case, we can instead just compute the receiver object on-demand by calculating the address of the parent
operation_state object from the address of the child operation_state object and can avoid needing to store the receiver
containing the pointer to the parent object.

This may seem a small win on an individual operation level, but if you have complex sender-compositions where
there might be many-levels-deep nesting of operation-states all allocated inline in a single top-level operation-state
then this can quickly add up to a saving of many pointer-sized receivers (plus any additional padding necessary).

Further, when a leaf operation wants to look up some context on the receiver (e.g. get_stop_token(r)) which then
forwards this query up the chain of parent receivers, this often results in pointer-chasing.
e.g. one receiver contains a pointer to parent operation-state then loads next receiver from that operation-state
which then needs to load the next receiver from the next operation-state etc.
This means calling get_stop_token() on a leaf receiver when the stop-token is provided 5 levels up will require
5 sequential pointer-dereferences to obtain the stop-token.

If instead, we are able to calculate the address of the parent operation-state as an offset from the child operation
state then getting the address of the top-level operation-state containing the stop-token just becomes subtracting
the relative offset of each child-operation in its parent and applying this successively to get the address of the
top-level operation-state. The compiler can then easily constant-fold these offsets to reduce it to a single offset
from the leaf operation-state.

Applying this optimisation has the potential to both reduce the size of operation-state objects, increasing cache
locality, reducing memory pressure, etc, but also to improve performance of receiver queries by avoiding the
pointer-chasing stack-walk behaviour that composed operations currently need to do.


This optimisation relies on the ability to calculate the address of the parent-object given the address of the sub-object,
however, which is not currently possible to do without invoking undefined behaviour.

So consider this a +1 from me for adding something like this to the standard.
Please also feel free to add this as additional motivation for the paper.

Let me know if there is anything I can do to help move this forward.

Cheers,
Lewis.

On Mon, Aug 22, 2022 at 9:07 AM Michael Scire via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
I e-mailed std::proposals about this last year (std::parent_of_member/std::containing_object_of_member), and got as far as writing a proposal paper, though I got too busy to submit it as a P-numbered proposal/etc.


I am still interested in submitting the above, and it's the same fundamental operation you're requesting here.

On Sun, Aug 21, 2022 at 4:23 PM Phil Bouchard via Std-Proposals <std-proposals@lists.isocpp.org> wrote:


On 8/21/22 19:10, Walt Karas wrote:
Yes I'd bet big this technique is an often reinvented wheel.

Why do you prefer two static casts involving void * over a reinterpret cast? Also, your C style cast is really a reinterpret cast. I think the reason for having reinterpret cast is that it's a (greppable) warning that something is dangerous.  And this technique is fairly dangerous, mistakes can elude static checking.

Yeah I just got the habit of not using any reinterpret_casts from the Boost community standards, so it's just another way of writing them down.

And I wasn't sure how alignments and little to big endian machines would convert them.



On Sun, Aug 21, 2022 at 4:38 PM, Phil Bouchard via Std-Proposals
--
Logo
Phil Bouchard facebook icon
CTO
T: (819) 328-4743
E: phil@fornux.com | www.fornux.com
1188 rue Saint-Louis | Gatineau (Qc), J8T 2L8 Canada
Banner Le message ci-dessus, ainsi que les documents l'accompagnant, sont destinés uniquement aux personnes identifiées et peuvent contenir des informations privilégiées, confidentielles ou ne pouvant être divulguées. Si vous avez reçu ce message par erreur, veuillez le détruire.
This communication (and/or the attachments) is intended for named recipients only and may contain privileged or confidential information which is not to be disclosed. If you received this communication by mistake please destroy all copies.
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals