Formalize public API, namespace, and release policy
I'd like to see us have at most two levels of nesting in namespaces: a top-level hpx and hpx::modulename. I'd even slightly prefer having everything in the public API be directly in hpx to make things easier to find ("I know the include and type that I want, but what namespace is it in?"), but things like std::execution::par make me think that we can have one level of nested namespaces for modules. This leaves the question of what gets to go directly in the top-level namespace? Should everything eventually move to a hpx::modulename namespace? Any functionality that we reimplement from the standard library should be in the same namespace as in the standard library (std replaced with hpx; e.g. hpx::util::tuple should be hpx::tuple). Perhaps aliasing from hpx::modulename to hpx:: for standard library functionality would be a reasonable solution.
On top of this I'd like to see things that we don't want to maintain compatibility for and things that see a lot of churn in hpx::modulename::detail (or hpx::detail). New features should always first go into hpx::modulename::experimental (or hpx::experimental) where they're allowed to change without warning and once stable enough they can move one level up. In short: detail would be for things that are never intended to be public. experimental is for things that should be public eventually but are not stable enough to warrant that.
I'd rather be more conservative with this and have too much in detail/experimental than too much in the public API. It's easy to make things public.
Once there is a concensus on this I think we can start aliasing things into the correct namespaces and once it's time to start thinking about HPX 2 we can remove definitions from the wrong namespaces.
I suppose this could do with a HEP (like #4593) to work out the details.
Before that I'd like to go one step further than what I proposed above, and say that I think we should expose the public API directly in the hpx:: namespace, with the exception of standard facilities that are not directly in std::. Motivation:
- Easier for users; if we tell a user to use
X, andXis in our public API, it'll behpx::Xwithout the user having to figure out which moduleXis in. - Easier for us; it protects us from having to set up compatibility options for module renamings and other shuffling around.
- With our current API mostly things that we explicitly alias or define in
hpx::will be part of the public API. Not much can end up in our public API by accident. Things that already are directly inhpx::should most likely stay there.
On 3.: It does not tell a user in which header they will find X, but they can if they're lazy just include collective headers.
The main difficulty I see is with some lcos that have the same name for local and distributed versions. In these cases I would go for explicit hpx::X_local and hpx::X_distributed names.
Related to this are of course headers, and we would have the same problem with module headers if we don't do anything there. I'd say maintaining compatibility headers for module renamings is easier though. Headers like hpx/hpx.hpp again protect us and users against reshuffling, and we could set up similar headers for the configurations we end up with in #4593.
Edit: Exposing the public API in hpx:: does not mean that we can't keep things in hpx::modulename:: internally.
If we agree to do the above, the follow-up is to make an explicit list of what the public API contains. I would keep that list in the documentation with direct links to the documentation. That would also it easier to check that our public API is actually documented, and users can be pointed to one page with the public API instead of having to sift through the documentation for modules. I believe this list would be significantly shorter than the full list of documented classes and functions that we have right now.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.