Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtual serialization: Eliminate need to name parent class in macro arguments #138

Open
PhilMiller opened this issue Oct 8, 2020 · 8 comments
Assignees

Comments

@PhilMiller
Copy link
Member

Follow-on/companion to #132.

@PhilMiller PhilMiller self-assigned this Oct 8, 2020
@lifflander
Copy link
Contributor

Here's my idea. Say we have some arbitrary classes registered: A, B, C, D and we don't know what relationship they are in. We call std::is_base_of<X, Y> for all pairs which tells if Y is a derived class of X. If the hierarchy is A <- B <- C <- D,

is_base_of<A, D> = true
is_base_of<A, C> = true
is_base_of<A, B> = true

Thus, A is the first base class because all returned true. We remove A from the list since it's the first comparison with all true outputs.
Then, we apply recursively starting with B.

is_base_of<B, C> = true
is_base_of<B, D> = true

I think the idea of dynamic_cast might also work.

@lifflander
Copy link
Contributor

Also, this might be insane but can we do something with sizeof?

@PhilMiller
Copy link
Member Author

I like the is_base_of line of thought, and we'd be able to topologically sort on the relationships if we could do it. Problem is, that's template stuff, and so we'd need a compile time list of the classes involved. Can't get that with separate compilation.

I don't think there's anything to be done with sizeof

@PhilMiller
Copy link
Member Author

For reference, here's the private message I sent earlier:

I just had a thought on a really cheesy but seemingly workable way to handle arbitrary single-rooted multiple inheritance (I.e. semi-lattice of types). Have a registry associated with the root. Each class inserts a function into the registry that takes a BaseT*b, tries to dynamic_cast<DerivedT*>(b), and calls serialize on that if it succeeds. Then, to serialize such an object, just iterate through the whole registry, calling every entry! This ignores the possibility of ordering dependencies between serializers, but we can get there with some topological sorting or something.

@PhilMiller
Copy link
Member Author

PhilMiller commented Oct 9, 2020

My initial suggestion is O(c) in the number of classes in a lattice, for each serialization operation. It would be nice if we instead could memoize by having that function return true/false, and remembering which ones return true. It would cut that down to O(#ancestors), which is optimal.

I don't think we can do that just once at the registry level, though, because we need actual instances in hand on which to call dynamic_cast

@PhilMiller
Copy link
Member Author

Thinking about this some more, my "some topological sorting" isn't really an answer to the serializer ordering problem. It should not be too hard to run the root before any of the others, but everything else seems much harder.

@PhilMiller
Copy link
Member Author

One thought is that we could add a member int level to ObjectEntry, with root being 0, and descendants statically counting up in a template that walks up the inheritance hierarchy until it hits the root. That definitely covers a forest of types (i.e. many trees, each with a root of a singly-inherited hierarchy). I think it can cover multiple inheritance too, by calling everything at level k before anything at level k+1.

@PhilMiller
Copy link
Member Author

There's another challenge I just noticed: if each class doesn't explicitly know its PARENT and call PARENT::_checkpointDynamicSerialize, there's no guarantee that the parent class has ever had makeObjIdx called for it, and thus it may not be registered at all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants