Skip to content

Commit 84b8e7c

Browse files
authored
Merge pull request #623 from eclipse-score/mf_update_design_move_logic
mw/com/design: Move logic
2 parents 23ea9c4 + b54e037 commit 84b8e7c

1 file changed

Lines changed: 50 additions & 15 deletions

File tree

score/mw/com/design/skeleton_proxy/README.md

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -92,26 +92,28 @@ The following sequence shows the instantiation of a service class up to its serv
9292

9393
<img alt="SKELETON_CREATE_OFFER_SEQ" src="https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/communication/refs/heads/main/score/mw/com/design/skeleton_proxy/skeleton_create_offer_seq.puml">
9494

95-
#### Binding independent level Registration of skeleton events/fields at their parent skeleton
95+
#### Binding independent level Registration of skeleton events/fields/methods at their parent skeleton
9696

9797
Due to our architectural constraints, the `impl::SkeletonBase` (the base class of the generated skeleton/`DummySkeleton`)
98-
doesn't "know" its event/field children. Because events/fields are the members of the generated skeleton and not the
99-
`impl::SkeletonBase`. But for various functionalities, we require the `impl::SkeletonBase` to have access to its
100-
events/fields.
101-
This is solved by a mechanism, where the event/field members of the generated skeleton class register themselves at
102-
their parent skeleton, which they got by reference during their creation/`ctor` call. So in their `ctor` they are
103-
calling `impl::SkeletonBase::RegisterEvent()` resp. `impl::SkeletonBase::RegisterField()`, with their own reference and
104-
name. So after creation of a generated skeleton, its base class (`impl::SkeletonBase`) has all the event/field members
105-
stored in `protected` members `events_` and `fields_`, so that in the future these could be even made `public`
106-
accessible to the generated (user facing) skeleton. Since these user facing skeletons have discrete event/field
107-
members anyhow, there is currently no need for such a generalized event/field access.
108-
109-
So while we have this relation/accessibility of events/fields from the "parent" skeleton on the binding **independent**
98+
doesn't "know" its event/field/method children. Because events/fields/methods are the members of the generated skeleton
99+
and not the `impl::SkeletonBase`. But for various functionalities, we require the `impl::SkeletonBase` to have access to
100+
its children.
101+
This is solved by a mechanism, where the event/field/method members of the generated skeleton class register themselves
102+
at their parent skeleton, which they got by reference during their creation/`ctor` call. So in their `ctor` they are
103+
calling `impl::SkeletonBase::RegisterEvent()`, `impl::SkeletonBase::RegisterField()` or
104+
`impl::SkeletonBase::RegisterMethod()`, with their own `special reference` (see below) and name. So after creation of a
105+
generated skeleton, its base class (`impl::SkeletonBase`) has all the event/field/method members stored in `protected`
106+
members `events_`, `fields_` and `methods_`, so that in the future these could be even made `public`
107+
accessible to the generated (user facing) skeleton. Since these user facing skeletons have discrete event/field/method
108+
members anyhow, there is currently no need for such a generalized access.
109+
110+
So while we have this relation/accessibility of children from the "parent" skeleton on the binding **independent**
110111
level, we **don't** have a symmetric setup on the binding **dependent** level. The binding specific implementation of
111112
`SkeletonBinding`, where `impl::SkeletonBase` is dispatching to via the `pImpl` idiom doesn't "know" its corresponding
112-
binding specific events and fields, which would be represented **both** as `SkeletonEventBinding` (as our field is a
113+
binding specific events, fields, which would be represented **both** as `SkeletonEventBinding` (as our field is a
113114
composite, which dispatches to `impl::SkeletonEventBase`, which then &ndash; also via `pImpl` idiom &ndash; dispatches
114-
to the binding specific `SkeletonEventBinding` [see here](#../todo)).
115+
to the binding specific `SkeletonEventBinding` [see here](#../todo)). Nor does it know its binding specific methods,
116+
which would be represented as `SkeletonMethodBinding`.
115117

116118
This symmetry isn't currently needed as we don't have any use case yet, where on the binding dependent level our
117119
`lola::Skeleton` (implementing `SkeletonBinding`) would need to call functionality on its events/fields!
@@ -123,6 +125,39 @@ implementation of `SkeletonBinding`, since we do not have (yet) a field specific
123125
whether we have to deal with a "pure" event or the "event part" of a field, we would resort to checking the related
124126
`ElementFqId`, which contains this differentiation.
125127

128+
#### How we handle moving of skeletons and their events/fields
129+
130+
In the previous section we have seen, that impl::SkeletonEvent, impl::SkeletonField and impl::SkeletonMethod register
131+
themselves at their parent `impl::SkeletonBase` during their construction with a reference to their parent.
132+
The special reference is obviously not a normal reference, but a `ReferenceToMoveable<SkeletonEventBase>::Reference` type
133+
(or `ReferenceToMoveable<SkeletonFieldBase>::Reference` resp. `ReferenceToMoveable<SkeletonMethodBase>::Reference`).
134+
Why is that? If we stored a normal reference to the event/field/method in the parent skeleton, we would have the
135+
following problem: whenever the event/field/method instances get moved (which happens, when the user moves his outer
136+
skeleton instance), the references within the `impl::SkeletonBase` need to be updated. To accomplish this, the
137+
event/field/method instances would also need a reference to their parent () to do the update! This again complicates
138+
things further! In case the `impl::SkeletonBase` moves (also happens, when the user moves his outer skeleton instance),
139+
then also the parent reference has to be updated within all the event/field/method instances.
140+
141+
Our solution to this issue is the following:
142+
For each event/field/method instance, we store a `ReferenceToMoveable<T>::Reference` on the heap.
143+
`T` is in this case one of:
144+
145+
- `SkeletonEventBase`
146+
- `SkeletonFieldBase`
147+
- `SkeletonMethodBase`
148+
149+
This "special reference" is created during the construction of the event/field/method instance and is passed to the
150+
`impl::SkeletonBase` during the registration call by reference. But since the `ReferenceToMoveable<T>::Reference` is
151+
stored on the heap and is **neither** copyable nor moveable, it doesn't get moved when the event/field/method is moved!
152+
Instead, the `ReferenceToMoveable<T>::Reference` instance is updated with the new address of the moved event/field/method
153+
instance within the move constructor/move assign op of the event/field/method. So the `impl::SkeletonBase` always has a
154+
valid reference to the event/field/method instance, even if the user moves the outer skeleton instance as long as it
155+
uses the `ReferenceToMoveable<T>::Reference::Get()` API to access the event/field/method instance!
156+
157+
The mechanism to provide such a "special reference" for `impl::SkeletonEventBase`, `impl::SkeletonFieldBase` and
158+
`impl::SkeletonMethodBase` is realized by inheriting from `EnableReferenceToMoveableFromThis<T>`, where `T` is one of
159+
the above-mentioned types. making it a `CRTP` pattern!
160+
126161
#### LoLa binding level Registration of skeleton events/fields at their parent skeleton
127162

128163
Despite the last paragraph in the previous chapter, we are doing still "some registration" in our `LoLa`/shared-memory

0 commit comments

Comments
 (0)