Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
159 commits
Select commit Hold shift + click to select a range
77e9ff5
Project import generated by Copybara.
Apr 25, 2025
9a84d4d
Project import generated by Copybara.
Apr 25, 2025
56a1e53
Project import generated by Copybara.
Apr 25, 2025
c952087
Project import generated by Copybara.
May 12, 2025
7bdb700
OSAL QNX Neutrino MsgSend timeout desync test
May 7, 2025
8391255
lib_memory: region bounds
hoe-jo May 9, 2025
88b7b45
L3 Coverity warnings fix
May 8, 2025
a335793
safecp: Expose regular compiler features in safecpp
limdor May 12, 2025
a13358d
Revert "Revert "mw/com: Fix race condition in service discovery""
LittleHuba May 6, 2025
51c0e6d
memory/shared: Use central variable for compiler warnings
limdor May 12, 2025
4bf06c4
lib: Use central variable for compiler warnings
limdor May 12, 2025
84af9de
Merge pull request #358 from swh/joho_memory_region_bounds_coverage
May 12, 2025
c2d4630
copybara: Add rules for LoLa and support different modules
castler May 7, 2025
24a035a
Merge pull request #386 from swh/js_copybara_for_lola
May 12, 2025
e84895c
Merge pull request #382 from swh/xb_clean_shared
May 13, 2025
777564e
lib/containers: suppress autosar a0-1-3
May 9, 2025
c32f881
Merge pull request #395 from swh/nick_fileutils
May 13, 2025
3290674
Update include guards and various smaller changes
castler May 14, 2025
5a469a4
lib/memory: Do not depend on @googletest
castler May 19, 2025
e44f0de
Fix MISRA rule 6.7.1 violations
BMW-Contributor May 19, 2025
6b40d79
copybara: Small optimizations
castler May 20, 2025
62bc8c7
Adapt configs after sctf migration
BMW-Contributor May 19, 2025
7e39e7d
memory region bounds: increase coverage
BMW-Contributor May 20, 2025
19d00d4
Merge pull request #509 from swh/joho_fix_coverage_memory_region_bounds
BMW-Contributor May 20, 2025
9b96fbc
lib/result: suppress autosar m6-4-1
BMW-Contributor May 20, 2025
5be94d5
Merge pull request #513 from swh/nick_lib_res_err
BMW-Contributor May 20, 2025
3531332
containers: fix coverage dynamic array
BMW-Contributor May 20, 2025
e3d8195
Merge pull request #511 from swh/joho_coverage_containers_dynamic_array
BMW-Contributor May 21, 2025
0e6e15c
memory_region_bounds: fix visibility tests
BMW-Contributor May 21, 2025
17cc8d7
scoped_function_invoker_test: fix visibility
BMW-Contributor May 21, 2025
11cfb21
Merge pull request #532 from swh/joho_scoped_function_fix_test_visibi…
BMW-Contributor May 21, 2025
1e63710
Merge pull request #531 from swh/joho_change_visibility_for_test_ddad
BMW-Contributor May 21, 2025
4915a0f
copybara: Add Ulrich Huber to allow OSS authors
LittleHuba May 16, 2025
5e79d9c
Revert "Fix coverity findings"
BMW-Contributor May 16, 2025
5ad7133
Added Alvaro Silva to allowed OSS authors
May 19, 2025
621d193
Merge pull request #461 from swh/ulhu_add_copybara
BMW-Contributor May 22, 2025
a7d3745
Add unit test suites for host and qnx
BMW-Contributor Jun 3, 2025
95d41b4
Updated project after restructuring
BMW-Contributor Jul 18, 2025
0f4fd69
Split lib/memory/shared unit tests
BMW-Contributor Jul 28, 2025
70b97be
Refactor lib/memory/shared unit tests
BMW-Contributor Jul 29, 2025
5269df5
Split lib/memory/shared unit tests
BMW-Contributor Jul 30, 2025
66f8e6e
Make amp::span explicitely to amp::v1::span
BMW-Contributor Jul 29, 2025
f4903af
memory: Add missing deps
castler Jul 31, 2025
de29f53
Boost dependency refactored
Rahul-Sutariya Aug 26, 2025
0f8bbfa
The error handling for the Store() API has been added.
BMW-Contributor Jul 15, 2025
e86d2f4
bazel: use boost targets from third_party_common
BMW-Contributor Jul 8, 2025
4a9574c
boost: use full include paths
BMW-Contributor Jul 18, 2025
6e0455c
Check : Check if memory is in typed memory
BMW-Contributor Jul 31, 2025
242f28a
make repo compliant again after updating clang-format to version 19
stmuench Aug 4, 2025
308dba8
Revert "Make amp::span explicitely to amp::v1::span"
BMW-Contributor Jul 31, 2025
5ddee66
lib/memory: Remove unused Double-Inversed-Int
castler Aug 5, 2025
375be21
lib/memory: Remove any_string_view
limdor Jun 20, 2025
bf9605f
clang-format: insert missing newlines to end of source code files
stmuench Aug 18, 2025
4fc69a5
Adapt GTL to handle daemon termination behaviour
Aug 27, 2025
5753b0e
Move test to separete test suite
BMW-Contributor Sep 4, 2025
986fa38
Agreggate target to test suite
BMW-Contributor Sep 9, 2025
21b286c
lib/utils: Move time_conversion to lib/datetime_converter
ahmed0mousa Sep 18, 2025
946bf0b
lib/memory: fix/mark suspicious accesses to string_view's underl. buffer
stmuench Sep 18, 2025
331838a
Decouple mw::log backend for test vs. production in lib/memory/shared
BMW-Contributor Sep 24, 2025
587323b
typedmemd: Unlink API
BMW-Contributor Jul 28, 2025
8c9273f
lib/memory/shared: suppress "fixed size member" related warning
gdadunashvili Oct 8, 2025
daf262b
mw/com/impl/util: Add utils for type erased storage
crimson11 Oct 3, 2025
47a9ac3
typedmemd: unlink API unit tests
BMW-Contributor Oct 6, 2025
fa32c81
bazel: blank line between copyright banner and load statements
fbaeuerle Oct 14, 2025
f7fb411
bazel: rename module from score-baselibs to score_baselibs
fbaeuerle Oct 28, 2025
4a5da79
Convert Base Libs Detailed Design for Shared Memory in Score Format
Sep 1, 2025
f333d23
memory/shared: Take MemProxy allocation into account in user allocations
bemerybmw Oct 22, 2025
fad733d
memory/shared: Record memory deallocated in MyBoundedMemoryResource
bemerybmw Oct 23, 2025
83d9aa7
memory/shared: Update MyBoundedMemoryResource to allocate like a shm res
bemerybmw Oct 31, 2025
6fcfe83
memory/shared: Create build file for fake resources
bemerybmw Nov 3, 2025
295b9df
memory/shared: Add MyBoundedSharedMemoryResource
bemerybmw Nov 3, 2025
444d29d
mw/com: Move DataTypeSizeInfo to lib/memory/shared
bemerybmw Oct 30, 2025
dcf7fc3
mw/com: Add suppression for banned-function memcpy
bemerybmw Nov 5, 2025
cf3ff5b
memory/shared: Add CalculateAlignedSizeOfSequence
bemerybmw Nov 3, 2025
3d4821f
memory/shared: Move DataTypeSizeInfo to memory
bemerybmw Nov 12, 2025
172edba
memory/shared: Address review comments
bemerybmw Nov 14, 2025
1c22038
memory: Add alignment check to DataTypeSizeInfo
bemerybmw Nov 14, 2025
60cd1b1
memory: Replace lambda with variable
bemerybmw Nov 17, 2025
d2f8d7f
Address review comments
bemerybmw Nov 17, 2025
8613534
typedmemd: remove unlink workaround calls
BMW-Contributor Oct 10, 2025
3de1b40
typedmemd: query shm object creator UID
BMW-Contributor Nov 5, 2025
d0218cb
typedmemd: UTs for Unlink and creator query UID
BMW-Contributor Nov 5, 2025
52bb3ca
typedmemd: remove unlink review findings fixed
BMW-Contributor Nov 18, 2025
e27431a
memory/shared: Use ISharedMemoryResource in shm initialize callback
bemerybmw Nov 14, 2025
4320211
memory::shared: Argue maybe-uninitalized warning
castler Nov 20, 2025
f70cf4d
typedmemd: KPI fixes
BMW-Contributor Nov 25, 2025
f0af11b
lib/memory/shared: Getter for log_identification
hoppe-and-dreams Nov 21, 2025
01fc185
lib/memory/shared: Deferring logging of error in Open()
hoppe-and-dreams Nov 20, 2025
435a9d3
memory/shared: Fix formatting
LittleHuba Nov 19, 2025
c5ac519
memory/shared: Ban utility functions
LittleHuba Nov 17, 2025
65ce47c
memory/shared: Fix typo in fixture names
bemerybmw Nov 18, 2025
53f0b55
memory: Assert that size is multiple of alignment in DataTypeSizeInfo
bemerybmw Nov 19, 2025
9160c2c
Remove dep of mw/log from test targets of lib/memory/shared
BMW-Contributor Nov 28, 2025
7bd0861
Remove dep of mw/log from test targets of lib/memory/shared
BMW-Contributor Nov 28, 2025
4c7cc2b
Revert changes of lib/memory/shared
BMW-Contributor Nov 28, 2025
cd6cbc5
Restore lib/memory/shared/**/BUILD
BMW-Contributor Dec 1, 2025
b0ddb17
memory/shared: Suppress "AUTOSAR C++14 A2-10-4" rule finding
LittleHuba Dec 2, 2025
77279c2
typedshm: coverity a15-5-3
BMW-Contributor Dec 16, 2025
d890bf1
typedsh: coverity m7-3-1
BMW-Contributor Dec 16, 2025
f58b95a
lib/memory/shared: coverity a3-3-1
BMW-Contributor Dec 16, 2025
2d1d772
lib/memory/shared: coverity a0-1-1
BMW-Contributor Dec 16, 2025
1af5344
lib/memory/shared: coverity m7-3-1
BMW-Contributor Dec 16, 2025
7a46c7a
lib/memory/shared: coverity a0-1-3
BMW-Contributor Dec 16, 2025
a123c57
lib/memory/shared: coverity a0-1-1
BMW-Contributor Dec 16, 2025
911dc05
lib/memory/shared: coverity a15-5-3
BMW-Contributor Dec 16, 2025
ed7efce
lib/memory/shared: coverity a12-4-1
BMW-Contributor Dec 16, 2025
159b726
lib/memory/shared: coverity m5-0-4
BMW-Contributor Dec 17, 2025
52555b4
lib/memory/shared: coverity m16-0-2
BMW-Contributor Dec 17, 2025
e69c0da
lib/memory/shared: coverity a4-7-1
BMW-Contributor Dec 17, 2025
ceef822
memory: coverage factory impl
BMW-Contributor Jan 9, 2026
8d7dd39
lib/memory/shared: coverity a12-1-5
BMW-Contributor Dec 17, 2025
5bed0f0
Shared memory: fix compiler warnings
BMW-Contributor Dec 18, 2025
3d2308d
lib/memory: replace unnecessary ptr arithmetic by more safe alternatives
stmuench Dec 18, 2025
8369747
score: add missing copyright headers
fbaeuerle Jan 16, 2026
109782f
lib/memory/shared: coverage gap
BMW-Contributor Jan 15, 2026
da2072e
lib/memory: git rid of safecpp's null-termination check
stmuench Jan 20, 2026
278b317
UML: Fixed kroki broken links.
BMW-Contributor Jan 19, 2026
cb10d42
Address review comments.
BMW-Contributor Jan 19, 2026
3c05a95
safecpp: suppress incorr. QCC deprecation warnings f. `std::char_traits`
stmuench Jan 22, 2026
b7e210d
typedmemd: remove hardcoded UID
BMW-Contributor Jan 15, 2026
0c7ae20
Updated copybara rule to fix kroki urls.
BMW-Contributor Jan 28, 2026
6fd1c88
log error when a call fails
muhseth Jan 29, 2026
6160f08
lib/memory: Boundscheck on []-operator for OffsetPtr
castler Jan 29, 2026
b9b4d92
lib/memory: Remove trailing whitespaces in bounds_check_test.cpp
castler Jan 29, 2026
2b84dfe
typedmemd: lld updated of unlink feature
BMW-Contributor Jan 29, 2026
8102f60
typedmemd: lld updated of unlink feature
BMW-Contributor Feb 3, 2026
bd7a23a
lib/memory: Add misisng new line after copyright header
BMW-Contributor Feb 5, 2026
d9a848f
memory/shared: Explicitly load rules_cc and rules_python load
limdor Feb 10, 2026
a39e8db
Fix copybara rules to enable bazel query.
BMW-Contributor Feb 13, 2026
0d298dc
acquire typedmemd uid fix
BMW-Contributor Feb 4, 2026
943683a
lib/memory: Add generated svg files to have a better user experience
limdor Feb 24, 2026
b969544
Add missing include for sys/types.h in typed_memory_utils.h
4og Feb 24, 2026
b7016c3
fix: add copyright header to generate_diagrams.sh
4og Feb 25, 2026
9d9a8b1
memory/shared: Add ticket number to the todo
limdor Feb 25, 2026
b33634e
lib/memory: Add clang tidy checks for header guards
limdor Feb 25, 2026
a53c07a
memory/shared: Add missing ticket number to the todo
limdor Feb 25, 2026
0d50a37
Restrict MemoryResourceProxy access and update allocator API
jorgecasal Feb 17, 2026
58450a0
lib/memory: update UML diagrams
fbaeuerle Feb 25, 2026
6c44e31
Moves transformation rules to common post.bara.sky
BMW-Contributor Feb 27, 2026
06f05fe
lib/memory: add missing copyright header
fbaeuerle Feb 27, 2026
9ef1d87
split_string_view: Migrate from amp to std string_view
limdor Feb 27, 2026
96d967c
Fix allocation failure log to show correct start address
BMW-Contributor Mar 15, 2026
d4adc06
remove unnecessary lock in SharedMemoryResource::do_deallocate
ShoroukRamzy Feb 22, 2026
720a3ca
Update shared_memory_resource.cpp
BMW-Contributor Jan 29, 2026
99cc1cc
Spelling correction in error output
BMW-Contributor Mar 18, 2026
278ae36
feat: move score/memory from baselibs into communication
KrishaDeshkool Mar 23, 2026
0e4d4e5
fix: update Bazel refs from @score_baselibs//score/memory to //score/…
KrishaDeshkool Mar 23, 2026
35e817e
fix: add boost.container dep and use local baselibs override
KrishaDeshkool Mar 23, 2026
bc76459
refactor(memory): remove atomic indirection utilities
KrishaDeshkool Mar 24, 2026
cd5bfd1
refactor(memory): remove string utilities
KrishaDeshkool Mar 24, 2026
9ca7f75
build(memory): update BUILD after utilities removal
KrishaDeshkool Mar 24, 2026
19b83bb
refactor(memory/shared): update memory_region_map includes
KrishaDeshkool Mar 24, 2026
82eb196
refactor(mw/com): update imports after memory utilities migration
KrishaDeshkool Mar 24, 2026
c162276
refactor(memory): remove duplicate endianness, data_type_size_info, p…
KrishaDeshkool Mar 24, 2026
911e6d4
build(mw/com): repoint data_type_size_info deps to @score_baselibs
KrishaDeshkool Mar 24, 2026
821ccf7
refactor(memory/shared): replace primitive cc_library targets with al…
KrishaDeshkool Mar 24, 2026
3fb1d96
feat(memory/shared): add remaining shared memory utilities from baselibs
KrishaDeshkool Mar 24, 2026
075f473
Fix shared BUILD files to use local refs instead of @score_baselibs
KrishaDeshkool Mar 24, 2026
2fa8fb3
Add missing shared memory targets (lock_file, factory, resource, tests)
KrishaDeshkool Mar 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ common --http_timeout_scaling=2.0


common --@score_baselibs//score/json:base_library=nlohmann
common --@score_baselibs//score/memory/shared/flags:use_typedshmd=False
common --//score/memory/shared/flags:use_typedshmd=False
common --@score_logging//score/mw/log/flags:KRemote_Logging=False
common --//score/mw/com/flags:tracing_library=@score_baselibs//score/analysis/tracing/generic_trace_library/stub_implementation
common --extra_toolchains=@gcc_toolchain_x86_64//:cc_toolchain
Expand Down
10 changes: 6 additions & 4 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ bazel_dep(name = "buildifier_prebuilt", version = "8.2.1.2", dev_dependency = Tr

bazel_dep(name = "score_crates", version = "0.0.7", repo_name = "score_communication_crate_index")
bazel_dep(name = "boost.program_options", version = "1.87.0")
bazel_dep(name = "boost.container", version = "1.87.0")
bazel_dep(name = "boost.interprocess", version = "1.87.0")

bazel_dep(name = "download_utils", version = "1.2.2", dev_dependency = True)
Expand Down Expand Up @@ -227,12 +228,13 @@ single_version_override(
patches = ["//third_party/rule_doxygen:Doxyfile.patch"],
)

# Apply patch to fix visibility issue with interprocess_notification target
# NOTE: local_path_override is temporary for development.
# Once baselibs merges the interprocess_mutex visibility fix,
# replace with git_override pointing to that commit.
bazel_dep(name = "score_baselibs", version = "0.2.4")
git_override(
local_path_override(
module_name = "score_baselibs",
commit = "052c2f271be4239f97182b164f4903b8c88d6c72",
remote = "https://github.com/eclipse-score/baselibs.git",
path = "/home/q551424/score/baselibs",
)

bazel_dep(name = "score_logging", version = "0.1.0")
Expand Down
22 changes: 22 additions & 0 deletions score/memory/.clang-tidy-extra
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
#
# This configuration file contains extra clang-tidy
# checks which shall get performed for all source files
# residing in this directory as well as its subdirectories.
#

# NOTE: Please *NEVER* specify a wildcard pattern for enabling checks,
# such as `bugprone-*` or `performance-*`! Only disabling checks
# would be acceptable, e.g. `-bugprone-*` or `-performance-*` etc.
# Reason for such guideline is that, in case wildcards get used for
# enabling checks, upgrading the clang-tidy binary to a newer version
# would then implicitly enable the new checks available in the upgraded
# clang-tidy binary. And then our (voting) CI jobs which are performing
# the extra clang-tidy checks are highly subject to fail and code would
# have to be made compliant again first. And that would block and also
# prolong the version upgrade unnecessarily. Furthermore it is easier
# to immediately spot which checks exactly will get performed in
# case each one gets listed explicitly, as done below.
Checks: >
-*,
modernize-concat-nested-namespaces,
58 changes: 58 additions & 0 deletions score/memory/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# *******************************************************************************
# Copyright (c) 2025 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************

load("@score_baselibs//:bazel/unit_tests.bzl", "cc_unit_test_suites_for_host_and_qnx")
load("@score_baselibs//score/quality/clang_tidy:extra_checks.bzl", "clang_tidy_extra_checks")

package(default_visibility = [
"//score/memory:__subpackages__",
])

alias(
name = "string_literal",
actual = "@score_baselibs//score/string:string_literal",
deprecation = "Use @score_baselibs//score/string:string_literal directly. This alias will be removed.",
visibility = ["//visibility:public"],
)

alias(
name = "string_comparison_adaptor",
actual = "@score_baselibs//score/string:string_comparison_adaptor",
deprecation = "Use @score_baselibs//score/string:string_comparison_adaptor directly. This alias will be removed.",
visibility = ["//visibility:public"],
)

alias(
name = "split_string_view",
actual = "@score_baselibs//score/string:split_string_view",
deprecation = "Use @score_baselibs//score/string:split_string_view directly. This alias will be removed.",
visibility = ["//visibility:public"],
)

cc_unit_test_suites_for_host_and_qnx(
name = "unit_test_suite",
test_suites_from_sub_packages = [
"//score/memory/shared:unit_test_suite",
],
visibility = [
"//visibility:public",
],
)

clang_tidy_extra_checks(
name = "clang_tidy_extra_checks",
extra_features = [
"spp_code_style_check_header_guards",
],
tidy_config_file = ".clang-tidy-extra",
)
6 changes: 6 additions & 0 deletions score/memory/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Memory

We need different utility libraries to handle memory. One of them being custom allocators but also handling shared
memory is a common problem.

This library shall be a single place to abstract common memory related use-cases.
5 changes: 5 additions & 0 deletions score/memory/design/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Software Design Description

This library holds an implementation to work with shared memory (see shared_memory folder).

Besides that it holds multiple utility functions to work with different parts of memory.
208 changes: 208 additions & 0 deletions score/memory/design/shared_memory/OffsetPtrDesign.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
# Offset Pointer

## Overview

When mapping shared memory into different processes, the shared memory block will be mapped to a different
virtual address space in each process.
While it is theoretically possible to enforce that the shared memory block is always mapped at the same base address in
each process, this is rather impractical, since it cannot be ensured that any given memory address is still free for use
in each process.

This means that using pointers or using complex data structures that rely on pointers in shared memory is non-trivial.
A pointer created in shared memory in one process pointing to an address in the same shared memory region will
not be valid in another process. `boost::interprocess` solves this problem with introducing a so-called
[OffsetPtr](https://www.boost.org/doc/libs/1_64_0/doc/html/boost/interprocess/offset_ptr.html).
The C++-Standard names such pointers also `fancy pointer`.

The idea of an `OffsetPtr` is that instead of storing an address of the pointed-to object (like a normal pointer), it
stores the offset between the address of the pointed-to object and the address of the `OffsetPtr` itself.
This offset is the same in all processes, thus, a valid pointer can be calculated as the sum of the base address of the
`OffsetPtr` and the offset that it stores.

Validity of the `OffsetPtr` depends on the validity of the pointed to object.
This means, that the absolute pointer handed to the constructor of `OffsetPtr<T>` must point to a valid object of type `T` (or derived).
Users must make sure that the `OffsetPtr` is valid before dereferencing it.
E.g. make sure that the `OffsetPtr` is not dereferenced after the object is destructed or moved-from.

The available public member methods are taken over from the `boost::interprocess::offset_ptr` implementation.
In order to reuse this pointer also with stl-based containers it shall implement the requirements stated by
[std::pointer_traits](https://en.cppreference.com/w/cpp/memory/pointer_traits).

### Bounds Checking OffsetPtr

For safety reasons, it is important that when accessing the memory pointed to by an `OffsetPtr` (either by dereferencing
the `OffsetPtr` or getting a raw pointer from the `OffsetPtr` and dereferencing that), the *entire* pointed-to object
must lie inside the original memory region in which the `OffsetPtr` was created (
See [this](../../../../docs/features/ipc/lola/ipnext_README.md#shared-memory-handling) for an explanation of why bounds
checking must be done).

From a safety perspective, the point of bounds checking is to prevent a lower safety rated process from interfering with
the memory of a higher safety rated process.
Currently, this is only an issue when dealing with shared memory.
However, in the future, we may have other memory resources which also require bounds checking.
e.g. memory pools in which we want to make sure that the `OffsetPtr` is not pointing to an address outside that pool.
Therefore, we have a generic interface for bounds checking that doesn’t depend on the type of memory.

Since we may have multiple memory resources which should be bounds checked, the `MemoryResourceRegistry` provides the
public interface for these checks.
An `OffsetPtr` does not know in which region / type of memory it has been allocated, so it is up to the
`MemoryResourceRegistry` to determine the relevant memory resource and memory bounds, if there are any, associated with
a given `OffsetPtr`.
This also means that bounds checking has to be attempted every time an `OffsetPtr` is dereferenced, even if the
`OffsetPtr` is in a type of memory that doesn’t need to be bounds checked.
Each class deriving from `ManagedMemoryResource` (e.g. `SharedMemoryResource`) can decide whether the memory that it is
managing should be bounds checked by an `OffsetPtr`.
It does this by implementing the function `ManagedMemoryResource::IsOffsetPtrBoundsCheckBypassingEnabled()`.

[Bounds checking](./generated/svg/bounds_checking.svg)
contains a minimalistic UML diagram of the bounds checking.

#### Bounds Checking Performance - Memory Bounds Lookup

Our simple integration tests and feedback from customers revealed, that the bounds checking functionality will be hit
very frequently!
In our 1st straight forward implementation approach, the MemoryResourceRegistry::GetBoundsFromAddress() function
acquired a reader-lock as we had to care for consistency between readers asking for bounds and writers, which update the
current bounds by inserting/removing resources.
But this solution based on a reader-writer lock turned out to be a big performance penalty.

Our current solution to access the bounds within the `MemoryResourceRegistry` concurrently between readers and writers
is the following:

* there can be only one writer active at a time. So writers get "serialized" by a "normal" mutex. I.e. all writer
activity to the bounds are routed through one of the following APIs, which already care for writer serialization:
`insert_resource()`, `remove_resource()`, `clear()`
* there can be an arbitrary number of readers active, which do a bounds-lookup (this happens during OffsetPtr deref)
* the algo to synchronize the access between the single writer and the multiple readers of the bounds is a lock-free
algo based on versioning and is detailed in the next subchapter.

So as we have lock-free access to the bounds for our readers, the footprint/runtime during the (high frequency
bounds-checking is very low, which also some benchmarks revealed (see [here](../../shared/test/performance).

##### Lock-Free bounds-check algorithm

The known bounds (aka known regions) are stored in a map (`std::map<const void*, const void*>`) containing the start
address of the region as key and its end address as value.
For our lock-free algo, we are maintaining N versions of this known regions/map and an indicator, which of the N
versions is the current/most recent one.

## OffsetPtr Implementation

Points to be considered in implementation can be seen
in [Problems to solve](./offset_ptr_problems.md#problems-to-solve).

### Bounds checking - OffsetPtr in shared memory

When an `OffsetPtr` is in a shared memory region, we can perform bounds checks by getting the memory bounds of that
region from the MemoryResourceRegistry using the address of the OffsetPtr (via
`MemoryResourceRegistry::GetBoundsFromAddress`).
We then check that the start address and end address of the pointed-to object lie within the retrieved memory bounds.
We also check that the entire `OffsetPtr` fits within the shared memory region.

### Bounds checking - OffsetPtr on stack

If the `OffsetPtr` is copied out of the memory region in which it was originally created, we still need to perform
bounds checks before dereferencing / getting a raw pointrer from the `OffsetPtr`.
Therefore, when copying an `OffsetPtr` from shared memory to the stack, we get the `MemoryResourceIdentifier` of the
memory resource from the `MemoryResourceRegistry` and store it within the `OffsetPtr`.
When dereferencing / getting a raw pointer from an `OffsetPtr` on the stack, we can get the memory bounds of the
`OffsetPtr`'s memory region with `MemoryResourceRegistry::GetBoundsFromIdentifier`.
We can use these bounds to check that the pointed-to object is still within that memory region.

When the `OffsetPtr` is copied back into shared memory, the `MemoryResourceIdentifier` is no longer used, since it can
be corrupted by another process, so we have to again use `MemoryResourceRegistry::GetBoundsFromAddress` to look up
memory bounds for bounds checking.
If the `OffsetPtr` is copied back to the stack, then the `MemoryResourceIdentifier` will be looked up again.

### Dereferencing / Getting OffsetPtr\<void\>

An `OffsetPtr` can be templated with `void`.
This can be useful for applications in which type-erasure of the pointed-to type is required.
However, this means that the `OffsetPtr` does not know the size of the pointed-to object, which is required for checking
that the start **and** end address of the pointed-to object lies within the correct memory region.
Therefore, we provide two additional `get()` overloads when the pointed-to type is void to allow the user to provide the
size information used to check that the end address of the pointed-to object also lies within the correct memory region:

* `get<ExplicitPointedType>`: This allows the caller to provide the actual PointedType as a template argument.
* `get(explicit_pointed_type_size)`: This allows the caller to provide the size of the PointedType as a function
argument. This is useful if the size of the pointed-to object is not known at compile time (and hence cannot be
derived from a type), e.g. if we have an OffsetPtr pointing to a type erased array of dynamic size.

### Copying OffsetPtr

As outlined in [One-past-the-end-iterators](./offset_ptr_problems.md#definitions--background), doing a bounds check on a
one-past-the-end iterator may fail if the container lies at the end of the memory region.
However, we want to support the ability to copy a one-past-the-end iterator.
Therefore, we have to make sure that copying an `Offsetptr` does not perform bounds checking (even when copying out of
shared memory).
Since bounds checking only needs to be done before getting a raw pointer from the `OffsetPtr` or dereferencing it (which
can also be done [if the `OffsetPtr` has been copied to the stack](#dereferencing--getting-offsetptr-on-the-stack)), we
can simply avoid doing any bounds checks when copying without violating any safety goals.

### Bounds check "race conditions"

Since an OffsetPtr residing in shared memory could be corrupted *during* bounds checking, we must ensure that the offset
value (or any other value which resides in shared memory such as a `MemoryResourceIdentifier`) is first copied to the
stack where it cannot be corrupted by another process.
This copy should be used for bounds checking and once checked, it should be used for dereferencing, getting a raw
pointer etc.

### Pointer Arithmetic Considerations

In the implementation of an `OffsetPtr` as described above, we need to perform pointer arithmetic in two places:

1. When constructing or copying an `OffsetPtr`, we need to subtract the address of the `OffsetPtr` itself from the
address of the pointed-to object.
2. When dereferencing an `OffsetPtr`, we need to add the calculated offset to the address of the `OffsetPtr`.

In (1.), subtracting two pointers which do not point to elements of the same array is undefined behaviour according to
the [standard](https://timsong-cpp.github.io/cppwp/n4659/expr.add#5).
In (2.), if adding an integral type to a pointer results in an address which does not point to an element of the same
array, then this is also undefined behaviour according to
the [standard](https://timsong-cpp.github.io/cppwp/n4659/expr.add#4).
To deal with these issues, we first cast the address to an integral type, and then do the addition / subtraction on the
integral types instead of pointers.
We can then cast the integral type back to a pointer, if required.
The conversion of a pointer to an integral type and an integral type to a pointer are implementation
defined: https://timsong-cpp.github.io/cppwp/n4659/expr.reinterpret.cast#4
and https://timsong-cpp.github.io/cppwp/n4659/expr.reinterpret.cast#5, respectively.
In this way, all "pointer arithmetic" is now actually integer arithmetic which is implementation defined.
We rely on having sufficient tests to ensure that the implementation behaves as we expect.

## DynamicArray Considerations

### Bounds checking iterators / element access

LoLa uses [DynamicArrays](../../../containers/dynamic_array.h) for
its [ServiceDataStorage](../../../../mw/com/impl/bindings/lola/service_data_storage.h)
and [ServiceDataControl](../../../../mw/com/impl/bindings/lola/service_data_control.h).
A `DynamicArray` is a fixed-size array data structure whose size can be, dynamically set at construction.
Since these both reside in shared memory, the underlying pointer type used by `DynamicArray` must be an `OffsetPtr`.
The `DynamicArray` is therefore susceptible to similar issues of memory corruption as an `OffsetPtr`.

For example, if the `OffsetPtr` to the underlying array is corrupted, then it may point to an address outside the
correct memory region or to an address that begins within the memory region, but the end address of the array (i.e. the
start address + the array size) would reside outside the memory region.

When accessing any elements via `at()` or `operator[]`, we must check that the element lies in the correct memory
region.
This is automatically done since we use an `OffsetPtr` to point to the array, so dereferencing an element will already
perform bounds checking.
However, when getting any iterators or pointers from the `DynamicArray`, we must first check that the entire underlying
array lies in the correct memory region.
We can do this by performing an `OffsetPtr` bounds check on the first and last elements of the array.
Since the array is contiguous, if the first and last elements are within the region, then all elements are.
We do the check on the first **and** last elements since the iterators return raw pointers which can be incremented /
decremented to dereference any element of the array.

### One-past-the-end-iterator

As outlined in [One-past-the-end-iterators](./offset_ptr_problems.md#definitions--background), doing a bounds check on a
one-past-the-end iterator may fail if the container lies at the end of the memory region.
Since the `DynamicArray` uses raw pointers as iterators, it needs to get a raw pointer from the one-past-the-end
`OffsetPtr` (e.g. in `end()`) which does bounds checking which may fail.
Therefore, we provide an additional `get()` overload called `GetWithoutBoundsCheck()` which the `DynamicArray` can use *
*only** for getting the raw pointer from the one-past-the-end `OffsetPtr`.
To prevent the user from decrementing this iterator and dereferencing it without any bounds checks, the `DynamicArray`
manually does bounds-checking on the start and end elements as
described [above](#bounds-checking-iterators--element-access).
Loading