LCOV - code coverage report
Current view: top level - include/hpactor/mem - alloc_header.hpp (source / functions) Coverage Total Hit
Test: HPActor Coverage Lines: 100.0 % 33 33
Test Date: 2026-05-20 02:24:49 Functions: 100.0 % 11 11
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : // Copyright 2026 HPActor Contributors
       2                 :             : //
       3                 :             : // Licensed under the Apache License, Version 2.0 (the "License");
       4                 :             : // you may not use this file except in compliance with the License.
       5                 :             : // You may obtain a copy of the License at
       6                 :             : //
       7                 :             : //     http://www.apache.org/licenses/LICENSE-2.0
       8                 :             : //
       9                 :             : // Unless required by applicable law or agreed to in writing, software
      10                 :             : // distributed under the License is distributed on an "AS IS" BASIS,
      11                 :             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :             : // See the License for the specific language governing permissions and
      13                 :             : // limitations under the License.
      14                 :             : 
      15                 :             : #pragma once
      16                 :             : 
      17                 :             : #include <hpactor/mem/size_class.hpp>
      18                 :             : #include <hpactor/types/types.hpp>
      19                 :             : 
      20                 :             : #include <cstddef>
      21                 :             : #include <cstdint>
      22                 :             : 
      23                 :             : namespace hpactor::mem {
      24                 :             : 
      25                 :             : inline constexpr uint32_t kAllocMagic = 0xAC70AC70;
      26                 :             : inline constexpr uint32_t kFreedMagic = 0xDEADDEAD;
      27                 :             : 
      28                 :             : // Forward declaration
      29                 :             : struct AllocHeader;
      30                 :             : 
      31                 :             : // ---------------------------------------------------------------------------
      32                 :             : // CanaryFooter: 8-byte canary at the end of every block
      33                 :             : // ---------------------------------------------------------------------------
      34                 :             : // Defined before AllocHeader to avoid circular dependency.
      35                 :             : // from_header() takes the block size explicitly rather than computing it from
      36                 :             : // AllocHeader::block_size(), which would require the complete type.
      37                 :             : struct alignas(8) CanaryFooter {
      38                 :             :     uint32_t magic{0};
      39                 :             :     uint32_t checksum{0};
      40                 :             : 
      41                 :             :     static void stamp(AllocHeader* header, size_t block_sz) noexcept;
      42                 :             : 
      43                 :             :     // block_sz: the total block size (user_size + overhead), from size_for_class()
      44                 :     1155171 :     static CanaryFooter* from_header(AllocHeader* header, size_t block_sz) noexcept {
      45                 :             :         return reinterpret_cast<CanaryFooter*>(
      46                 :     1155171 :             reinterpret_cast<std::byte*>(header) + block_sz - sizeof(CanaryFooter));
      47                 :             :     }
      48                 :             : 
      49                 :           2 :     static bool verify(const AllocHeader* header, size_t block_sz) noexcept {
      50                 :           2 :         auto* f = from_header(const_cast<AllocHeader*>(header), block_sz);
      51                 :           2 :         return f->magic == kAllocMagic;
      52                 :             :     }
      53                 :             : };
      54                 :             : 
      55                 :             : // ---------------------------------------------------------------------------
      56                 :             : // AllocHeader: 32-byte metadata prefix on every block
      57                 :             : // ---------------------------------------------------------------------------
      58                 :             : struct alignas(32) AllocHeader {
      59                 :             :     // owner_id when live; next when freed (freelist linkage via union)
      60                 :             :     union {
      61                 :             :         uint64_t owner_id;
      62                 :             :         AllocHeader* next;
      63                 :             :     };
      64                 :             :     uint32_t incarnation{0};
      65                 :             :     uint32_t magic{kAllocMagic};
      66                 :             :     uint8_t  size_class{0};
      67                 :             :     uint8_t  generation{0};
      68                 :             :     uint16_t flags{0};
      69                 :             :     uint32_t _padding{0};
      70                 :             :     uint64_t timestamp{0};
      71                 :             : 
      72                 :     1155168 :     static AllocHeader* stamp(void* block, SizeClass sc, ActorId owner) noexcept {
      73                 :     1155168 :         auto* h = static_cast<AllocHeader*>(block);
      74                 :     1155168 :         h->owner_id = owner.value();
      75                 :     1155168 :         h->incarnation = 0;
      76                 :     1155168 :         h->magic = kAllocMagic;
      77                 :     1155168 :         h->size_class = static_cast<uint8_t>(sc);
      78                 :     1155168 :         h->generation = 0;
      79                 :     1155168 :         h->flags = 0;
      80                 :     1155168 :         h->_padding = 0;
      81                 :     1155168 :         h->timestamp = 0;
      82                 :     1155168 :         return h;
      83                 :             :     }
      84                 :             : 
      85                 :     1255282 :     void* user_data() noexcept {
      86                 :     1255282 :         return reinterpret_cast<std::byte*>(this) + sizeof(AllocHeader);
      87                 :             :     }
      88                 :             : 
      89                 :     2309206 :     static AllocHeader* from_user_data(void* user_ptr) noexcept {
      90                 :             :         return reinterpret_cast<AllocHeader*>(
      91                 :     2309206 :             static_cast<std::byte*>(user_ptr) - sizeof(AllocHeader));
      92                 :             :     }
      93                 :             : 
      94                 :           1 :     static std::byte* user_ptr(std::byte* block) noexcept {
      95                 :           1 :         return block + sizeof(AllocHeader);
      96                 :             :     }
      97                 :             : 
      98                 :             :     // Returns pointer to the CanaryFooter for this block
      99                 :           1 :     std::byte* footer_ptr() const noexcept {
     100                 :             :         return reinterpret_cast<std::byte*>(const_cast<AllocHeader*>(this))
     101                 :           1 :                + block_size() - sizeof(CanaryFooter);
     102                 :             :     }
     103                 :             : 
     104                 :           1 :     bool is_live() const noexcept { return magic == kAllocMagic; }
     105                 :           1 :     bool is_freed() const noexcept { return magic == kFreedMagic; }
     106                 :             : 
     107                 :           1 :     size_t block_size() const noexcept {
     108                 :           1 :         return mem::block_size(static_cast<SizeClass>(size_class));
     109                 :             :     }
     110                 :             : 
     111                 :             :     size_t user_size() const noexcept {
     112                 :             :         return mem::size_for_class(static_cast<SizeClass>(size_class));
     113                 :             :     }
     114                 :             : };
     115                 :             : 
     116                 :             : // Out-of-line because it needs AllocHeader complete type
     117                 :     1155168 : inline void CanaryFooter::stamp(AllocHeader* header, size_t block_sz) noexcept {
     118                 :     1155168 :     auto* f = from_header(header, block_sz);
     119                 :     1155168 :     f->magic = kAllocMagic;
     120                 :     1155168 :     f->checksum = 0;
     121                 :     1155168 : }
     122                 :             : 
     123                 :             : } // namespace hpactor::mem
        

Generated by: LCOV version 2.0-1