[OpenMethod] Questions about custom policies.

Hello, I just started with review and I have a cluster of questions, but it is not clear what the root cause of my issues is so apologies if ordering of questions is wrong. 1. I wanted to get hash map stats, but they are not printed in debug policy, even when env variable is set, I must hack release policy like this: - vptr_vector<release>, vectored_error_handler<release>> {}; + vptr_vector<release>, vectored_error_handler<release>, basic_trace_output<release>> {} Is this expected? IDK why debug prints some trace, but not hash info 2. While playing with this I get crashes when I just c/p release policy and rename it, e.g. +struct my_release : basic_policy< + my_release, std_rtti, fast_perfect_hash<my_release>, + vptr_vector<my_release>, vectored_error_handler<my_release>> {}; crashes in template<bool Indirect> inline auto box_vptr(const vptr_type& vp) { if constexpr (Indirect) { return &vp; } else { return vp; } } but when I switch boost::openmethod::initialize<boost::openmethod::policies::my_release>(); to boost::openmethod::initialize<boost::openmethod::policies::release>(); it works fine. It also exibits some other weird behavior, e.g. if I switch debug inheritance from release to my_release crash goes away, even when not using debug... Looks to me I am doing something that is not allowed, but it is not clear what I am doing wrong. regards, Ivan

Hi,
1. I wanted to get hash map stats, but they are not printed in debug policy, even when env variable is set
There is a small bug here. If you try with the "review" branch, or use <https://raw.githubusercontent.com/jll63/Boost.OpenMethod/refs/heads/review/flat/boost/openmethod.hpp> in compiler explorer, you will get the hash stats. See https://godbolt.org/z/bneKT6s7v Now an important thing: if you build with NDEBUG defined, the default policy is debug. Otherwise it is release. I suspect that in your examples, NDEBUG is not set. Thus the classes and methods are added to the *debug* policy.
2. While playing with this I get crashes when I just c/p release policy and rename it, e.g. +struct my_release : basic_policy< + my_release, std_rtti, fast_perfect_hash<my_release>, + vptr_vector<my_release>,
This creates a new policy, from scratch. Its catalog of classes and methods is distinct from the debug policy's - and it's empty. You need to use my_release consistently. For example: BOOST_OPENMETHOD( poke, (std::ostream&, virtual_ptr<Animal, my_release>), void, my_release); ^^^^^^^^^^^^ ^^^^^^^^^^^^ BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog, Bulldog, my_release); ^^^^^^^^^^^^ int main() { boost::openmethod::initialize<my_release>(); ^^^^^^^^^^^^ ... } Compiler Explorer: https://godbolt.org/z/MGs1eMd8W Of course it is rather cumbersome to add the policy as a second argument to virtual_ptr everywhere. At this point, you can create an alias: template<typename T> using my_ptr = virtual_ptr<T, my_release>; BOOST_OPENMETHOD( poke, (std::ostream&, my_ptr<Animal>), void, my_release); You can also globally override the policy: #include <boost/openmethod/policies.hpp> using namespace boost::openmethod::policies; struct my_release : basic_policy< my_release, std_rtti, fast_perfect_hash<my_release>, vptr_vector<my_release>, vectored_error_handler<my_release>> {}; // BEFORE including <boost/openmethod.hpp> #define BOOST_OPENMETHOD_POLICY my_release #include <boost/openmethod.hpp>
It also exibits some other weird behavior, e.g. if I switch debug inheritance from release to my_release crash goes away, even when not using debug...
If you mean what I think ;) it is because `debug` is the default policy in the absence of NDEBUG.
Looks to me I am doing something that is not allowed, but it is not clear what I am doing wrong.
Policies and facets are definitely an advanced feature. J-L On Wed, Apr 30, 2025 at 7:36 AM Ivan Matek via Boost <boost@lists.boost.org> wrote:
Hello, I just started with review and I have a cluster of questions, but it is not clear what the root cause of my issues is so apologies if ordering of questions is wrong.
1. I wanted to get hash map stats, but they are not printed in debug policy, even when env variable is set, I must hack release policy like this: - vptr_vector<release>, vectored_error_handler<release>> {}; + vptr_vector<release>, vectored_error_handler<release>, basic_trace_output<release>> {} Is this expected? IDK why debug prints some trace, but not hash info
2. While playing with this I get crashes when I just c/p release policy and rename it, e.g. +struct my_release : basic_policy< + my_release, std_rtti, fast_perfect_hash<my_release>, + vptr_vector<my_release>, vectored_error_handler<my_release>> {}; crashes in template<bool Indirect> inline auto box_vptr(const vptr_type& vp) { if constexpr (Indirect) { return &vp; } else { return vp; } } but when I switch
boost::openmethod::initialize<boost::openmethod::policies::my_release>(); to
boost::openmethod::initialize<boost::openmethod::policies::release>();
it works fine. It also exibits some other weird behavior, e.g. if I switch debug inheritance from release to my_release crash goes away, even when not using debug...
Looks to me I am doing something that is not allowed, but it is not clear what I am doing wrong.
regards, Ivan
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Wed, Apr 30, 2025 at 4:32 PM Jean-Louis Leroy via Boost < boost@lists.boost.org> wrote:
Hi,
1. I wanted to get hash map stats, but they are not printed in debug policy, even when env variable is set
There is a small bug here. If you try with the "review" branch, or use < https://raw.githubusercontent.com/jll63/Boost.OpenMethod/refs/heads/review/f...
in compiler explorer, you will get the hash stats. See https://godbolt.org/z/bneKT6s7v
Now an important thing: if you build with NDEBUG defined, the default policy is debug. Otherwise it is release. I suspect that in your examples, NDEBUG is not set. Thus the classes and methods are added to the *debug* policy.
2. While playing with this I get crashes when I just c/p release policy and rename it, e.g. +struct my_release : basic_policy< + my_release, std_rtti, fast_perfect_hash<my_release>, + vptr_vector<my_release>,
This creates a new policy, from scratch. Its catalog of classes and methods is distinct from the debug policy's - and it's empty.
You need to use my_release consistently. For example:
BOOST_OPENMETHOD( poke, (std::ostream&, virtual_ptr<Animal, my_release>), void, my_release); ^^^^^^^^^^^^ ^^^^^^^^^^^^ BOOST_OPENMETHOD_CLASSES(Animal, Cat, Dog, Bulldog, my_release); ^^^^^^^^^^^^
int main() { boost::openmethod::initialize<my_release>(); ^^^^^^^^^^^^ ... }
Compiler Explorer: https://godbolt.org/z/MGs1eMd8W
Of course it is rather cumbersome to add the policy as a second argument to virtual_ptr everywhere. At this point, you can create an alias:
template<typename T> using my_ptr = virtual_ptr<T, my_release>;
Hi, thank you for the answer, review branch prints out hashing stats. Few follow up questions. 1. Why virtual_ptr doesn't just pick up the policy that was used in initialize? I presume to avoid some runtime performance overhead. 2. Should this behavior be more explicitly mentioned in the documentation. I was reading documentation and assumed I can just provide my policy in initialize, it was not clear to me what you explained here. I mean now I know how things work it is obvious https://jll63.github.io/Boost.OpenMethod/#tutorials_policies_and_facets is mentioning that initialize and virtual_ptr are "linked", but I think it is not obvious when reading it for the first time. 3. Why are we breaking here out of just 1 for loop? https://github.com/jll63/Boost.OpenMethod/blob/4e4dff8059f94b07c201036c0e918...

Hi, thank you for the answer, review branch prints out hashing stats.
And if you wanted to, you could derive a facet implementation that measures the time it took to find the hash factors, or implement perfect _minimal_ hashing, etc.
Why virtual_ptr doesn't just pick up the policy that was used in initialize? I presume to avoid some runtime performance overhead.
Yes. It annoys me that we have to specify the policy so many times. I have an idea, but it's whacky, probably a very bad idea: the method and overriders could infuse the virtual_ptr with the method's policy - just like you don't need to give the overrider the policy, it gets it from the method.
Should this behavior be more explicitly mentioned in the documentation. I was reading documentation and assumed I can just provide my policy in initialize, it was not clear to me what you explained here. I mean now I know how things work it is obvious https://jll63.github.io/Boost.OpenMethod/#tutorials_policies_and_facets is mentioning that initialize and virtual_ptr are "linked", but I think it is not obvious when reading it for the first time.
The documentation needs work, obviously.
Why are we breaking here out of just 1 for loop?
You mean after just one collision? Because we are looking for a perfect (aka collision-free) very simple and fast hash function: (value * M) >> S. M and S are found by random search. See a collision? Try another M. After a certain number of attempts, double S. J-L

On Thu, May 1, 2025 at 1:24 AM Jean-Louis Leroy via Boost < boost@lists.boost.org> wrote: > You mean after just one collision? > > I meant this - for (auto iter = first; iter != last; ++iter) { + for (auto iter = first; found && iter != last; ++iter) { i.e. I think break does not "break enough". As soon you got collision you need to give up and pick new random hash.
participants (2)
-
Ivan Matek
-
Jean-Louis Leroy