File size: 3,894 Bytes
f7ccd08
 
 
32b4893
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
{ SPDX-License-Identifier: LicenseRef-Sovereign-Leviathan-SL-AGPL3-001
   Licensing: see LICENSE in the repository root. }

{ Buffer: Physical storage management with generation tracking.
  Implements allocation, reference counting, and generation counters
  for temporal safety (use-after-free detection).

  Key properties:
    - Generational tracking: each buffer has monotonically increasing generation
    - Arc semantics: refcount > 1 indicates shared ownership
    - Memory safety: generation validation prevents stale references
}

unit buffer;

{$MODE FPC}

interface

type
  { Buffer metadata }
  TBuffer = record
    { Allocated data }
    data: ^single;

    { Physical size in elements }
    size: uint32;

    { Reference count (Arc semantics) }
    refcount: uint32;

    { Generation counter for temporal safety }
    generation: uint32;
  end;

  PBuffer = ^TBuffer;

{ Allocate a new buffer with given size }
function AllocateBuffer(size: uint32): PBuffer;

{ Free a buffer (when refcount reaches 0) }
procedure FreeBuffer(var buf: PBuffer);

{ Increment reference count (Arc::clone equivalent) }
procedure CloneBuffer(buf: PBuffer);

{ Decrement reference count }
procedure ReleaseBuffer(var buf: PBuffer);

{ Check if buffer is exclusively owned (refcount = 1) }
function IsExclusivelyOwned(buf: PBuffer): boolean;

{ Get current generation of buffer }
function GetGeneration(buf: PBuffer): uint32;

{ Increment generation on mutation }
procedure IncrementGeneration(buf: PBuffer);

{ Validate that generation matches expected }
function ValidateGeneration(buf: PBuffer; expected: uint32): boolean;

{ Zero-initialize a buffer region }
procedure ZeroBuffer(buf: PBuffer; size: uint32);

{ Copy data from source to destination buffer }
procedure CopyBufferData(
  src: PBuffer; src_offset: uint32;
  dst: PBuffer; dst_offset: uint32;
  count: uint32
);

implementation

var
  { Global generation counter for allocation tracking }
  global_generation: uint32 = 0;

function AllocateBuffer(size: uint32): PBuffer;
var
  buf: PBuffer;
begin
  new(buf);
  if buf = nil then
    exit(nil);

  getmem(buf^.data, size * sizeof(single));
  if buf^.data = nil then
  begin
    dispose(buf);
    exit(nil);
  end;

  buf^.size := size;
  buf^.refcount := 1;
  buf^.generation := global_generation;
  inc(global_generation);

  { Zero-initialize }
  ZeroBuffer(buf, size);
  result := buf;
end;

procedure FreeBuffer(var buf: PBuffer);
begin
  if buf = nil then
    exit;

  if buf^.data <> nil then
    freemem(buf^.data);

  dispose(buf);
  buf := nil;
end;

procedure CloneBuffer(buf: PBuffer);
begin
  if buf <> nil then
    inc(buf^.refcount);
end;

procedure ReleaseBuffer(var buf: PBuffer);
begin
  if buf = nil then
    exit;

  dec(buf^.refcount);
  if buf^.refcount = 0 then
    FreeBuffer(buf)
  else
    buf := nil;
end;

function IsExclusivelyOwned(buf: PBuffer): boolean;
begin
  if buf = nil then
    result := false
  else
    result := (buf^.refcount = 1);
end;

function GetGeneration(buf: PBuffer): uint32;
begin
  if buf = nil then
    result := 0
  else
    result := buf^.generation;
end;

procedure IncrementGeneration(buf: PBuffer);
begin
  if buf <> nil then
  begin
    inc(buf^.generation);
    inc(global_generation);
  end;
end;

function ValidateGeneration(buf: PBuffer; expected: uint32): boolean;
begin
  if buf = nil then
    result := false
  else
    result := (buf^.generation = expected);
end;

procedure ZeroBuffer(buf: PBuffer; size: uint32);
var
  i: uint32;
begin
  if buf = nil then
    exit;

  for i := 0 to size - 1 do
    buf^.data^[i] := 0.0;
end;

procedure CopyBufferData(
  src: PBuffer; src_offset: uint32;
  dst: PBuffer; dst_offset: uint32;
  count: uint32
);
var
  i: uint32;
begin
  if (src = nil) or (dst = nil) then
    exit;

  for i := 0 to count - 1 do
    dst^.data^[dst_offset + i] := src^.data^[src_offset + i];
end;

end.