Skip to content

Commit

Permalink
doc, renames
Browse files Browse the repository at this point in the history
  • Loading branch information
jll63 committed Feb 21, 2024
1 parent 36dc147 commit 5b95eee
Show file tree
Hide file tree
Showing 13 changed files with 388 additions and 118 deletions.
17 changes: 8 additions & 9 deletions include/yorel/yomm2/policy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ struct yOMM2_API_gcc checked_perfect_hash : virtual fast_perfect_hash<Policy>,

if constexpr (Policy::template has_facet<error_handler>) {
unknown_class_error error;
error.context = unknown_class_error::call;
error.context = unknown_class_error::update;
error.type = type;
Policy::error(error);
}
Expand All @@ -563,15 +563,15 @@ template<class Policy>
std::vector<type_id> checked_perfect_hash<Policy>::control;

#ifdef __cpp_exceptions
struct yOMM2_API_gcc throw_error_handler : virtual error_handler {
struct yOMM2_API_gcc throw_error : virtual error_handler {
static void error(const error_type& error_v) {
std::visit([](auto&& arg) { throw arg; }, error_v);
}
};
#endif

template<class Policy>
struct yOMM2_API_gcc vectored_error_handler : virtual error_handler {
struct yOMM2_API_gcc vectored_error : virtual error_handler {
static error_handler_type error;

static void default_error_handler(const error_type& error_v) {
Expand Down Expand Up @@ -617,11 +617,11 @@ struct yOMM2_API_gcc vectored_error_handler : virtual error_handler {
};

template<class Policy>
error_handler_type vectored_error_handler<Policy>::error; // set by update!
error_handler_type vectored_error<Policy>::error; // set by update!

template<class Policy>
struct yOMM2_API_gcc backward_compatible_error_handler
: vectored_error_handler<Policy> {
: vectored_error<Policy> {
static method_call_error_handler call_error;

static void default_error_handler(const error_type& error_v) {
Expand All @@ -635,7 +635,7 @@ struct yOMM2_API_gcc backward_compatible_error_handler
abort();
}

vectored_error_handler<Policy>::default_error_handler(error_v);
vectored_error<Policy>::default_error_handler(error_v);
}

static void default_call_error_handler(
Expand Down Expand Up @@ -672,7 +672,7 @@ method_call_error_handler
template<class Policy, class... Facets>
struct yOMM2_API_gcc basic_static_policy
: basic_policy<
Policy, vptr_vector<Policy>, std_rtti, vectored_error_handler<Policy>,
Policy, vptr_vector<Policy>, std_rtti, vectored_error<Policy>,
Facets...> {};

template<class Policy, class... Facets>
Expand All @@ -698,8 +698,7 @@ struct debug_shared;
#if defined(_MSC_VER) && !defined(yOMM2_DLL)
extern template class __declspec(dllimport) basic_domain<debug_shared>;
extern template class __declspec(dllimport) vptr_vector<debug_shared>;
extern template class __declspec(dllimport)
vectored_error_handler<debug_shared>;
extern template class __declspec(dllimport) vectored_error<debug_shared>;
extern template class __declspec(dllimport) fast_perfect_hash<debug_shared>;
extern template class __declspec(dllimport) basic_policy<
debug_shared, vptr_vector<debug_shared>, std_rtti,
Expand Down
62 changes: 62 additions & 0 deletions reference.in/boilerplate/code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#define BOOST_TEST_MODULE ENTITY
#include <boost/test/included/unit_test.hpp>

/***

<sub>/ ->home / ->reference </sub>

entry: yorel::yomm2::ENTITY
headers: yorel/yomm2/core.hpp, yorel/yomm2/keywords.hpp

---
```
struct ENTITY;
```

TODO

## Template parameters

**TODO** - TODO

## static member functions
| | |
| ---- | ---- |
| TODO | TODO |

### TODO

```c++
TODO
```

TODO

#### Parameters

**TODO** - TODO.

#### Return value

TODO.

#### Errors

* TODO


### Example

***/

//***
#include <yorel/yomm2/keywords.hpp>

// for brevity
using namespace yorel::yomm2;

BOOST_AUTO_TEST_CASE(ref_TODO) {
TODO
}

//***
86 changes: 36 additions & 50 deletions reference.in/checked_perfect_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,43 +13,21 @@ headers: yorel/yomm2/policy.hpp, yorel/yomm2/core.hpp, yorel/yomm2/keywords.hpp
struct checked_perfect_hash;
```
`checked_perfect_hash` is an implementation of ->`type_hash`. It uses the following
hash function:
`checked_perfect_hash` is a subclass of ->`fast_perfect_hash`. It checks that
the id passed to `hash_type_index` is valid, i.e. was in the set of ids
registered via `hash_initialize`.
```
H(x) = (x * M) >> S
```
The output values are in the interval `[0, 1 << (N - S)[`, where `N` is the
bit size of `type_id`.
The `M` and `S` coefficients are determined during initialization so that, for
the given set of type ids, the hash function is _perfect_, i.e. collision-free.
It is not _minimal_: there may be gaps in the output interval.
`hash_type_id` must not be called with ids not present in the input set passed
to `hash_initialize`. This happens when the class of a virtual argument was not
registered via ->`use_classes` or ->`register_classes`. `ref_perfect_hash` will
silently return an index in the output range, to be used to fetch the v-table
for the class from a vector. From there, two things can happen. In the lucky
scenario, the index will correspond to a gap, a wasted entry in the v-table
vector, which will contain a null pointer. The program will segfault. Such
mistake is fairly easy to troubleshoot. In the unlucky scenario, there will be a
collision - the hash function is perfect only for the input ids - and the wrong
method will be called. The program will carry on, crashing far from the root
cause of the error, and, in the worst case, not at all.
To help detect such registration errors, it is highly recommended to run debug
builds of the program with ->`checked_perfect_hash`, which detects missing class
registrations.
## Interactions with other facets
`default_policy` uses `checked_perfect_hash` in release builds, and
`checked_perfect_hash` in debug builds.
* `error_handler` - to report error conditions.
* `error_output` - for diagnostics.
* `update_output` - for trace.
## Template parameters
**Policy** - the policy containing the facet.
## static member functions
| | |
| ----------------------------------- | ---------------------------- |
Expand All @@ -64,9 +42,10 @@ template <typename ForwardIterator>
static size_t hash_initialize(ForwardIterator first, ForwardIterator last)
```
Finds the `M` and `S` parameters of the hash function. `ForwardIterator` is an
iterator that satisfies the requirements of forward iterators; dereferencing it
yields a `type_id`. Sets `type_hash_last` to the maximum hash value, plus one.
Calls
[`fast_perfect_hash::hash_initialize`](fast_perfect_hash.md#hash_initialize).
Also build a reverse mapping, from hashed ids to registered ids.
#### Parameters
Expand All @@ -78,7 +57,7 @@ None.
#### Errors
None.
* Any exception thrown by Allocator::allocate() (typically std::bad_alloc).
### hash_type_id
Expand All @@ -87,8 +66,11 @@ template<class Policy>
static type_id hash_type_id(type_id type)
```
Returns the hashed value of `type`, which must be one of the values passed to
`hash_initialize`.
[`fast_perfect_hash::hash_type_index`](fast_perfect_hash.md#hash_initialize).
Retrieve the registered id corresponding to the hashed id. Compare it with
`type`. If they are the same, return the hashed value. If not, report an error
via `Policy::error` if `Policy` has an `error_handler` facet; otherwise,
abort the program.
#### Parameters
Expand All @@ -100,7 +82,7 @@ None.
#### Errors
None.
* ->`unknown_class_error`, with `context` set to `unknown_class_error::update`.
### Example
Expand All @@ -113,21 +95,25 @@ None.
using namespace yorel::yomm2;
using namespace yorel::yomm2::policy;

// Create a policy that contains 'checked_perfect_hash' and `throw_error`.
struct checked_policy
: basic_policy<checked_policy, checked_perfect_hash<checked_policy>,
throw_error_handler> {};
: basic_policy<
checked_policy, checked_perfect_hash<checked_policy>,
throw_error> {};

BOOST_AUTO_TEST_CASE(ref_check_checked_perfect_hash) {
std::vector<type_id> ids = {42, 1963, 602701};
checked_policy::hash_initialize(ids.begin(), ids.end());
bool caught = false;

try {
checked_policy::hash_type_id(666);
} catch (unknown_class_error &error) {
caught = true;
}

BOOST_TEST(caught);
std::vector<type_id> ids = {42, 1963, 602701};
checked_policy::hash_initialize(ids.begin(), ids.end());
bool caught = false;

try {
// 'fast_perfect_hash' would return a bogus result...
checked_policy::hash_type_id(666);
} catch (unknown_class_error& error) {
// ...but 'checked_perfect_hash' catches it.
caught = true;
}

BOOST_TEST(caught);
}
//***
2 changes: 1 addition & 1 deletion reference.in/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ following situations:
The function is allowed to throw an exception, `exit`, or anything it sees fit.
If it returns, the program is terminated with `abort`.

YOMM2 provides three implementations of the facet: `vectored_error_handler`. It
YOMM2 provides three implementations of the facet: `vectored_error`. It
calls the function specified in the `error` static member variable of the facet
- a `std::function<void(const error_type& error)>` -, passing it the error
variant.
Expand Down
48 changes: 48 additions & 0 deletions reference.in/error_handler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@


<sub>/ [home](/reference//README.md) / [reference](/reference//reference/README.md) </sub>

**yorel::yomm2::error_handler**<br>
<sub>defined in <yorel/yomm2/core.hpp>, also provided by<yorel/yomm2/keywords.hpp></sub>

---
```
struct ENTITY;
```

TODO

## Interactions with other facets

* `error_handler` - to report error conditions.
* `error_output` - for diagnostics.
* `update_output` - for trace.

## Template parameters

**TODO** - TODO

## static member functions
| | |
| ---- | ---- |
| TODO | TODO |

### TODO

```c++
TODO
```

TODO

#### Parameters

**TODO** - TODO.

#### Return value

TODO.

#### Errors

* TODO
46 changes: 26 additions & 20 deletions reference.in/fast_perfect_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ registrations.
`default_policy` uses `fast_perfect_hash` in release builds, and
`checked_perfect_hash` in debug builds.
## Interactions with other facets
* `error_handler` - to report error conditions.
* `error_output` - for diagnostics.
* `update_output` - for trace.
## Template parameters
**Policy** - the policy containing the facet.
Expand Down Expand Up @@ -79,7 +85,7 @@ None.
#### Errors
None.
* Any exception thrown by Allocator::allocate() (typically std::bad_alloc).
### hash_type_id
Expand Down Expand Up @@ -116,29 +122,29 @@ using namespace yorel::yomm2;
using namespace yorel::yomm2::policy;

struct fast_hash_policy
: basic_policy<fast_hash_policy, fast_perfect_hash<fast_hash_policy>> {
};
: basic_policy<fast_hash_policy, fast_perfect_hash<fast_hash_policy>> {};

BOOST_AUTO_TEST_CASE(ref_fast_perfect_hash) {
std::vector<type_id> ids = {42, 1963, 2001};
fast_hash_policy::hash_initialize(ids.begin(), ids.end());

for (auto id : ids) {
BOOST_TEST_MESSAGE(id << " -> " << fast_hash_policy::hash_type_id(id));
// Output:
// 42 -> 0
// 1963 -> 3
// 602701 -> 2

for (auto other : ids) {
BOOST_TEST((fast_hash_policy::hash_type_id(id) ==
fast_hash_policy::hash_type_id(other)) == (id == other));
std::vector<type_id> ids = {42, 1963, 2001};
fast_hash_policy::hash_initialize(ids.begin(), ids.end());

for (auto id : ids) {
BOOST_TEST_MESSAGE(id << " -> " << fast_hash_policy::hash_type_id(id));
// Output:
// 42 -> 0
// 1963 -> 3
// 602701 -> 2

for (auto other : ids) {
BOOST_TEST(
(fast_hash_policy::hash_type_id(id) ==
fast_hash_policy::hash_type_id(other)) == (id == other));
}
}
}

// Calling hash_type_id with an unregistered type_id returns bogus result:
BOOST_TEST_MESSAGE(666 << " -> " << fast_hash_policy::hash_type_id(666));
// 666 -> 3 !!!
// Calling hash_type_id with an unregistered type_id returns bogus result:
BOOST_TEST_MESSAGE(666 << " -> " << fast_hash_policy::hash_type_id(666));
// 666 -> 3 !!!
}

//***
Loading

0 comments on commit 5b95eee

Please sign in to comment.