Stroika Library 3.0d24
 
Loading...
Searching...
No Matches
StackBuffer.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Memory_StackBuffer_h_
5#define _Stroika_Foundation_Memory_StackBuffer_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
10
11/**
12 * \file
13 *
14 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
15 */
16
17namespace Stroika::Foundation::Memory {
18
19 namespace Support::StackBuffer {
20
21 /**
22 * On Windows, there is _chkstk which shows up in alot of profiles. Perhaps something similar for UNIX? Or just kernel does this automatically?
23 * Anyhow - target number we try - for performance reasons - to avoid more than this much in a stack frame.
24 *
25 * https://www.codeguru.com/visual-studio/adventures-with-_chkstk/
26 */
27 constexpr size_t kSizeIfLargerStackGuardCalled = qStroika_Foundation_Common_Platform_Windows ? (sizeof (int) == 4 ? 4 : 8) * 1024 : 16 * 1024;
28
29 /**
30 * \note good to keep this small (around 2k) for Windows, cuz else _chkstack calls end up litering profiles in alot of functions
31 * even if along paths not actually used. COULD optimize those paths with specific value in usages, but seems reasonable to keep
32 * to 2k for now --LGP 2023-09-12
33 */
34 constexpr size_t kTargetInlineByteBufferSize = qStroika_Foundation_Common_Platform_Windows ? 2 * 1024 : 4 * 1024;
35
36 /**
37 */
38 template <typename T = byte>
39 constexpr size_t DefaultInlineSize ()
40 {
41 // note must be defined here, not in inl file, due to use as default template argument
42 auto r = ((kTargetInlineByteBufferSize / sizeof (T)) == 0 ? 1 : (kTargetInlineByteBufferSize / sizeof (T)));
43 Ensure (r >= 1);
44 return r;
45 }
46
47 }
48
49 /**
50 * \brief Store variable sized (BUF_SIZE elements) array on the stack (\see also InlineBuffer<T,BUF_SIZE>), and on heap if it grows if needed
51 *
52 * Typically, StackBuffer<> combines the performance of using a stack buffer (inline array on stack) to store arrays with
53 * the safety and flexability of using the free store (malloc).
54 *
55 * \note StackBuffer<T,N> and InlineBuffer<T,N> are the SAME TYPE; StackBuffer is
56 * an alias - so the choice is about INTENT and about the default size, and is enforced by
57 * convention rather than by the compiler:
58 *
59 * o StackBuffer says "this buffer lives in a stack frame": a scratch buffer local to one
60 * function - marshalling, chunking a range before handing it off, accumulating a small
61 * result. THIS IS THE ONE TO USE for that, which is the common case.
62 * o InlineBuffer is the general-purpose form, and is what you want when the buffer is a
63 * DATA MEMBER of an object that may itself live on the heap - a context StackBuffer is
64 * not intended for.
65 *
66 * The default sizes follow from that intent, and are the one concrete difference:
67 * StackBuffer's default inline element count targets Support::StackBuffer::kTargetInlineByteBufferSize
68 * (deliberately only 2K on Windows, see the note there) to keep the frame below the size
69 * where _chkstk gets called - those calls litter profiles of every function along the path,
70 * including ones that never touch the buffer. InlineBuffer defaults to a flat 4K, which is
71 * fine for a heap-resident member, where that concern does not apply.
72 *
73 * Summary: stack frame -> StackBuffer. Data member -> InlineBuffer.
74 *
75 * \note Historical Note: InlineBuffer and StackBuffer used to be more different, but they did exactly the same thing. The only difference was
76 * the IDEA that StackBuffer might someday be re-implemented using alloca. I dont think thats plausible any longer, but something akin
77 * to it might be possible, so maintain the API difference for now.
78 */
79 template <typename T = byte, size_t BUF_SIZE = Support::StackBuffer::DefaultInlineSize<T> ()>
81
82}
83
84/*
85 ********************************************************************************
86 ***************************** Implementation Details ***************************
87 ********************************************************************************
88 */
89
90#endif /*_Stroika_Foundation_Memory_StackBuffer_h_*/
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...