Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions docs/project/code-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,30 @@ keys that reject copying, exact raw-pointer destruction and shared/borrowed valu

Check `it != values.end()` before incrementing or calling `get_key()` / `get_data()`. Empty ranges have `begin() == end()`; do not dereference or increment end. Advancing one iterator does not change a saved prior position, but removing its node, clearing or destroying its container ends that borrowed lifetime. The custom iterator and const-iteration APIs are otherwise unchanged. Core header checks instantiate scalar and pointer mappings; `check-core` covers saved postfix values, storage mutation, empty/end comparisons and the existing `array_map` lookup path.

## LRU cache copying and insertion

`<ark/container/lru_map.hpp>` stores values, recency keys and internal links as one
cache. Copies retain capacity and recency order, rebuild links into their own key
list, and remain usable after the source changes or is destroyed. Mapped values
retain their normal copy semantics, including shared ownership for `shared_ptr`.
Copying prepares empty container bookkeeping before rebuilding entries and links
from the oldest entry to the newest. Copy assignment prepares the replacement
before releasing existing entries; exceptions that propagate from allocation or
key/value copying leave both caches intact. This does not guarantee recovery from
allocation inside a standard-library `noexcept` path: MSVC Debug, for example,
allocates a hash-table iterator proxy in such a constructor.

Insertion of an existing key retains its original value and recency. Insertion
failure from allocation or key/value copying propagates the exception and removes
the incomplete entry; existing values and eviction order remain intact. `find()`
still promotes a found entry and successful insertion evicts the least recently
used entry when full. Public signatures and class fields are unchanged; rebuild
header consumers to use the fix. `check-lru-map`, also included in `check-core`,
covers independent copies, eviction, key-copy exceptions and isolated allocation
failures. Insertion injects failure at every allocation. Copying injects at every
content allocation starting with the first source lookup, after empty container
bookkeeping is ready; it does not inject into MSVC's `noexcept` proxy construction.

## POD array storage and failure contract

`<ark/array_pod.hpp>` retains its `void` mutation APIs and inline/heap storage layout. Use it for trivial scalar or pointer elements with a positive inline capacity; it does not manage nontrivial element lifetimes. `push_back`, fill `resize` and `insert` snapshot an element argument before growing or shifting storage, so an argument such as `values[0]` keeps its original value. Growth can still invalidate borrowed element pointers and references.
Expand Down
18 changes: 18 additions & 0 deletions docs/project/code-style_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,24 @@ clang-tidy 需要已配置构建的编译数据库及兼容的编译器工具链

递增或调用 `get_key()`/`get_data()` 前,先检查 `it != values.end()`。空范围满足 `begin() == end()`,不要解引用或递增 end。推进一个迭代器不改变已保存的旧位置,但移除对应节点、清空或销毁容器后,不再使用原借用。其余自定义迭代器与 const 迭代接口保持不变。Core 头文件检查实例化标量与指针映射;`check-core` 覆盖后置递增旧值、存储修改、空范围/end 比较,以及现有 `array_map` 查询路径。

## LRU 缓存复制与插入

`<ark/container/lru_map.hpp>` 将值、访问顺序键和内部链接作为一个缓存管理。
复制保留容量和访问顺序,并将链接重建到自己的键列表;源对象改变或销毁后,
复制体仍可使用。值保持原有复制语义,包括 `shared_ptr` 的共享所有权。
复制先准备空容器的内部管理状态,再从最久未使用的条目开始重建值和链接。
复制赋值先准备替换状态,再释放原有条目;分配或键/值复制向外传播的异常
不会改变两个缓存。这不保证能从标准库 `noexcept` 路径内的分配失败中恢复;
例如,MSVC Debug 会在此类构造函数中分配哈希表的迭代器代理。

插入已有键时,保留原值和访问顺序。分配或键/值复制失败时,异常向外传播,
不完整的新条目会被移除;原有值和淘汰顺序保持不变。`find()` 仍将命中条目移到
最近使用位置,满容量后的成功插入仍淘汰最久未使用的条目。公开签名和成员布局
保持不变;重新编译头文件使用方即可采用修复。`check-lru-map` 纳入 `check-core`,
覆盖独立复制、淘汰、键复制异常和隔离的分配失败。插入测试逐个分配注入失败;
复制测试在空容器内部管理状态就绪后,从首次查询源缓存开始逐个内容分配注入,
不向 MSVC 的 `noexcept` 代理构造过程注入失败。

## POD 数组存储与失败约定

`<ark/array_pod.hpp>` 保留 `void` 修改接口及内联/堆存储布局。它用于正内联容量的平凡标量或指针元素,不管理非平凡元素生命周期。`push_back`、带填充值的 `resize` 和 `insert` 会在扩容或移动前保存元素参数,因此 `values[0]` 等别名参数保留原值。扩容仍会使借用的元素指针和引用失效。
Expand Down
7 changes: 6 additions & 1 deletion docs/reference/mysql.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ See [build/runtime activation](build-options.md#native-database-plugins) and [ma
```cpp
ark::task<> update_player() {
auto begun = co_await database_->begin("primary", {std::chrono::seconds(5), std::chrono::seconds(1)});
if (!begun) { co_return; }
if (!begun || begun.transaction == 0 ||
begun.transaction_status.outcome != ark::mysql_transaction_outcome::active) {
co_return;
}
const auto id = begun.transaction;
std::vector<arknet::mysql::field_value> values{std::int64_t{42}};
auto changed = co_await database_->execute(id, "UPDATE players SET score=?", std::move(values));
Expand All @@ -79,6 +82,8 @@ ark::task<> update_player() {

Transactions hold one native lease. Monotonic IDs belong only to the issuing module instance, owning no implementation object. One operation per transaction; unknown/expired IDs or overlapping steps throw. The original timeout covers acquire, BEGIN, steps and commit without renewal. Unused transactions roll back at deadline; `cleanup_timeout` separately bounds rollback. Failed/uncertain cleanup discards the connection; no automatic retry or cross-connection replay.

Converting `mysql_reply` or `mysql_transaction_reply` to `bool` checks business success. A successful BEGIN can expire and roll back before owner delivery, returning no transaction ID; check both `transaction` and `transaction_status.outcome` before submitting a step.

`mysql_reply` retains the owning `arknet::mysql::query_result` and separate statement-close diagnostics. `mysql_transaction_reply` additionally retains rollback results, initiation failures and the final transaction status. Successful execution alone does not prove cleanup or commit succeeded. Native database/transport failures are returned; local C++ and bridge admission failures propagate as exceptions. Cancellation requests reach the native request and preserve `outcome_unknown` for a potentially executed statement.

## Execution, limits and shutdown
Expand Down
7 changes: 6 additions & 1 deletion docs/reference/mysql_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ ark::task<> run() {
```cpp
ark::task<> update_player() {
auto begun = co_await database_->begin("primary", {std::chrono::seconds(5), std::chrono::seconds(1)});
if (!begun) { co_return; }
if (!begun || begun.transaction == 0 ||
begun.transaction_status.outcome != ark::mysql_transaction_outcome::active) {
co_return;
}
const auto id = begun.transaction;
std::vector<arknet::mysql::field_value> values{std::int64_t{42}};
auto changed = co_await database_->execute(id, "UPDATE players SET score=?", std::move(values));
Expand All @@ -79,6 +82,8 @@ ark::task<> update_player() {

事务各步骤持有同一原生租约;递增标识只对签发模块实例有效,不拥有插件实现对象。同一事务仅允许一个操作,未知/过期标识或重叠步骤抛异常。原超时覆盖取连接、BEGIN、各步骤与提交,不续期;未使用事务到期回滚,`cleanup_timeout` 单独限制回滚。清理失败或不确定则丢弃连接,不自动重试或跨连接重放。

将 `mysql_reply` 或 `mysql_transaction_reply` 转为 `bool` 仅检查业务是否成功。BEGIN 成功后,事务仍可能在所属线程交付结果前到期并回滚,此时不返回事务标识;提交后续步骤前须同时检查 `transaction` 和 `transaction_status.outcome`。

`mysql_reply` 保留拥有型 `arknet::mysql::query_result` 及独立的预处理语句关闭诊断。`mysql_transaction_reply` 还保留回滚结果、启动异常和事务最终状态。执行成功并不代表清理或提交成功。数据库及传输错误返回原生结果,本地 C++ 异常和协程桥限额异常向调用方传播。取消请求会转交原生操作;语句可能已经执行时保留 `outcome_unknown`。

## 执行、限额与停机
Expand Down
62 changes: 53 additions & 9 deletions src/core/container/lru_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,25 @@ class lru_map
capacity_ = capacity > 0 ? capacity : 1024;
}

lru_map(const lru_map& other)
: lru_map(other.capacity_) {
// Prepare all container bookkeeping before copying entries. Rebuild each
// link in its final list instead of temporarily borrowing source links.
for (auto it = other.kl_.rbegin(); it != other.kl_.rend(); ++it)
{
insert(*it, other.kv_.at(*it));
}
}

lru_map& operator=(const lru_map& other) {
if (this != &other)
{
lru_map candidate(other);
swap(candidate);
}
return *this;
}

~lru_map() = default;

bool empty() const {
Expand Down Expand Up @@ -71,15 +90,40 @@ class lru_map
return;
}

kl_.push_front(key);
ki_[key] = kl_.begin();

if (kv_.size() > capacity_)
try
{
kl_.push_front(key);
try
{
const auto index = ki_.emplace(key, kl_.begin()).first;
try
{
if (kv_.size() > capacity_)
{
// Resolve both lookups before removing any existing entry.
const auto oldest_value = kv_.find(kl_.back());
const auto oldest_index = ki_.find(kl_.back());
kl_.pop_back();
kv_.erase(oldest_value);
ki_.erase(oldest_index);
}
}
catch (...)
{
ki_.erase(index);
throw;
}
}
catch (...)
{
kl_.pop_front();
throw;
}
}
catch (...)
{
key_type k = kl_.back();
kl_.pop_back();
kv_.erase(k);
ki_.erase(k);
kv_.erase(r.first);
throw;
}
}

Expand Down Expand Up @@ -117,4 +161,4 @@ class lru_map
size_t capacity_; // max capacity
};

} // namespace ark
} // namespace ark
12 changes: 12 additions & 0 deletions tests/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,18 @@ add_custom_target(check-buffer
USES_TERMINAL VERBATIM)
add_dependencies(check-core check-buffer)

# Allocation injection must not affect other Core runners.
add_executable(ark_lru_map_tests main.cpp lru_maps.cpp)
set_property(TARGET ark_lru_map_tests PROPERTY LINK_LIBRARIES ark::core)
add_executable(ark_lru_map_failure_tests main.cpp lru_map_failure.cpp)
set_property(TARGET ark_lru_map_failure_tests PROPERTY LINK_LIBRARIES ark::core)
add_custom_target(check-lru-map
COMMAND $<TARGET_FILE:ark_lru_map_tests>
COMMAND $<TARGET_FILE:ark_lru_map_failure_tests>
DEPENDS ark_lru_map_tests ark_lru_map_failure_tests
USES_TERMINAL VERBATIM)
add_dependencies(check-core check-lru-map)

# Isolate timer allocation hooks and Release-mode assertion fallback checks.
add_executable(ark_timer_tests main.cpp timers.cpp)
set_property(TARGET ark_timer_tests PROPERTY LINK_LIBRARIES ark::core)
Expand Down
6 changes: 6 additions & 0 deletions tests/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,3 +275,9 @@ for the public-layout rebuild requirement and service-validation limits.
`check-startup-cleanup` verifies one prepared owning capsule, a private wheel, four-stage failure, one-shot cleanup and emergency exit under persistent allocation failure. Six isolated allocation-failure cases distinguish failures before call entry from failures inside startup; a separate termination control checks the diagnostic and failure exit. Scalar/array throwing and nothrow allocation probes also verify matching deallocation, constructor-failure cleanup and persistent null results. Application builds also run 14 actual-launcher/separate-DSO cases. Shared Utility/IO and business rollback remain outside this scope; see [startup-failure cleanup](../../docs/project/startup-failure-cleanup.md).

`check-scalar-stream-allocation` isolates global allocation failure from ordinary tests and visits every allocation in scalar publisher construction, baseline copying, updates, first/replacement baseline reception and delta reception. Each failure preserves the committed state and retained values; retry advances exactly one revision. It is included in `check-entity-stream` and exercises long/binary strings plus all scalar alternatives.

`check-lru-map`, included in `check-core`, covers independent copy links, duplicate
insertion, capacity/recency behavior after swap, key-copy exceptions and isolated
allocation failures at every insertion and copy-assignment allocation. Failed
operations preserve existing entries, eviction order and retained value owners.
See [LRU cache contracts](../../docs/project/code-style.md#lru-cache-copying-and-insertion).
4 changes: 4 additions & 0 deletions tests/core/README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,7 @@ XXTEA 用例覆盖精确长度分配的短密钥、16 字节与内嵌零字节
`check-startup-cleanup` 验证一个预登记 owning capsule、私有时间轮、四阶段失败、一次性清理与持续分配故障紧急退出;六种隔离分配故障区分调用前失败与启动内部失败,另设异常终止对照用例检查诊断与失败退出。额外验证单对象及数组的 `new` 和 `new (std::nothrow)` 分配与释放匹配,并覆盖构造异常、持续分配失败返回空指针。启用应用时,还运行真实 launcher/独立测试 DSO 的 14 个场景。它不接入共享 Utility 或 IO,也不证明业务回滚;见[启动失败清理](../../docs/project/startup-failure-cleanup_CN.md)。

`check-scalar-stream-allocation` 独立运行全局分配失败注入,逐个遍历标量发布端构造、基线复制、更新、首次/替换基线接收和增量接收中的分配。失败保留已提交状态与旧拥有值,重试仅推进一次修订;用例包含长/二进制字符串及全部标量类型,已纳入 `check-entity-stream`。

`check-lru-map` 纳入 `check-core`,覆盖独立复制链接、重复插入、交换后的容量/
访问顺序、键复制异常,以及插入和复制赋值各分配点的隔离失败。失败操作保留原有
条目、淘汰顺序和值的拥有关系。见 [LRU 缓存契约](../../docs/project/code-style_CN.md#lru-缓存复制与插入)。
Loading
Loading