GCC Code Coverage Report


Directory: ./
File: include/na64util/mem/plainBlock.hh
Date: 2025-09-01 06:19:01
Exec Total Coverage
Lines: 11 19 57.9%
Functions: 11 24 45.8%
Branches: 1 2 50.0%

Line Branch Exec Source
1 #pragma once
2
3 /**\file
4 * \brief Provides implementation of simple short memory block
5 *
6 * A declaration of plain memory block allocation strategy.
7 * */
8
9 #include "na64util/mem/alloc.hh"
10 #include "na64util/str-fmt.hh"
11
12 #include <cassert>
13
14 namespace na64dp {
15 namespace errors {
16
17 /**\brief Indicates exhaustion of the statically pre-allocated block */
18 class PreallocatedBlockExhausted : public GenericRuntimeError {
19 public:
20 const void * blockPtr;
21 const size_t preallocatedBlockLength
22 , lastRequestedLength
23 ;
24
25 PreallocatedBlockExhausted( void * blockPtr_
26 , size_t preallocatedBlockLength_
27 , size_t lastRequestedLength_
28 ) : GenericRuntimeError( util::format(
29 "Pre-allocated memory block %p of"
30 " size %zub depleted with last"
31 " allocation of size %zub."
32 , blockPtr_
33 , preallocatedBlockLength_
34 , lastRequestedLength_
35 ).c_str() )
36 , blockPtr(blockPtr_)
37 , preallocatedBlockLength(preallocatedBlockLength_)
38 , lastRequestedLength(lastRequestedLength_)
39 {}
40 };
41
42 } // namespace ::na64dp::errors
43
44 namespace mem {
45
46 /**\brief A single, limited memory block
47 *
48 * This is an extremely simple allocator strategy implementation. It is
49 * designed for a single-pass with low allocations (in fact, it does not
50 * even de-allocates memory). It is expected that this allocator will
51 * leverage CPU cache for computation-intensive operations by avoiding
52 * memory fragmentation and benefit from CPU cache an small data chunks.
53 *
54 * Recommended usage is for short, CPU-intensive calculations with arithmetics,
55 * container lookup, with few insertions of data ~10kbytes. Do not use it for
56 * general purpose.
57 *
58 * \warning
59 * De-allocation of managed memory block is done only on the deletion of
60 * strategy itself.
61 * \warning
62 * Memory block capacity is limited, it won't resize on the overflow
63 */
64 class PlainBlock {
65 public:
66 typedef uint32_t Size_t;
67 private:
68 char *_block ///< First byte addr of mem block
69 , *_blockEnd ///< Last byte addr of mem block
70 , *_cur ///< Current position in mem block
71 ;
72 protected: // except for "Allocator<>"
73 ///\brief Allocates memory sub-block
74 ///
75 /// Accessed by `Allocator` instance.
76 67 template<typename T> T * acquire(Size_t sz) {
77 67 _cur += sz*sizeof(T);
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
67 if( _cur >= _blockEnd ) {
79 throw errors::PreallocatedBlockExhausted(
80 _block, _blockEnd - _block, sz);
81 }
82 67 return reinterpret_cast<T *>(_cur - sz*sizeof(T));
83 }
84 ///\brief Frees memory sub-block
85 ///
86 /// Accessed by `Allocator` instance.
87 86 template<typename T> void release(T * p, Size_t sz) {
88 // ... do nothing
89 }
90 ///\brief Returns maximum capacity of objects of certain type
91 ///
92 /// Accessed by `Allocator` instance.
93 template<typename T> Size_t max_for() const noexcept {
94 return (_blockEnd - _cur)/sizeof(T);
95 }
96 public:
97 /// Explicitly prohibit the copy ctr to avoid copying
98 PlainBlock( const PlainBlock & ) = delete;
99
100 /// Constructs the block of certain size (in bytes)
101 10 PlainBlock( void * blockBgn, size_t len ) {
102 10 _block = _cur = static_cast<char*>(blockBgn);
103 10 _blockEnd = _block + len;
104 10 }
105
106 /// Does nothing.
107 10 ~PlainBlock() {;}
108
109 /// Returns handle (allocator) to typed "pool"
110 template<typename T> Allocator<T, PlainBlock> of() { return Allocator<T, PlainBlock>(*this); }
111
112 /// Sets the "current" pointer to the beginning of the block, thus
113 /// invalidating all previous allocations.
114 18 void reset() { _cur = _block; }
115
116 #if 0
117 /// A "fast" object allocation method forwarding its arguments to ctr
118 ///
119 /// \returns `std::shared_ptr` with proper deleter
120 template<typename T, typename... Args> std::shared_ptr<T>
121 create_object( Args&&... args ) {
122 return std::allocate_shared< T, Allocator<T, PlainBlock> >(
123 of<T>(), std::forward<Args>(args)...);
124 }
125 #endif
126
127 template<typename T, typename Strategy> friend class Allocator;
128 };
129
130 #if 0
131 /// A "fast" object allocation function acting on top of our default allocator
132 template<typename T, typename... Args> std::shared_ptr<T>
133 fast_new( PlainBlock & alloc, Args&&... args ) {
134 return std::allocate_shared< T,
135 na64dp::mem::Allocator<T, PlainBlock> >( alloc.of<T>(),
136 std::forward<Args>(args)...);
137 }
138 #endif
139
140 } // namespace ::na64dp::mem
141 } // namespace na64dp
142
143