Skip to content

Commit acbd93b

Browse files
authored
builtin: add .nogrow and .nofree flags to array (#16661)
1 parent b07e447 commit acbd93b

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

vlib/builtin/array.v

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ pub mut:
2424
pub enum ArrayFlags {
2525
noslices // when <<, `.noslices` will free the old data block immediately (you have to be sure, that there are *no slices* to that specific array). TODO: integrate with reference counting/compiler support for the static cases.
2626
noshrink // when `.noslices` and `.noshrink` are *both set*, .delete(x) will NOT allocate new memory and free the old. It will just move the elements in place, and adjust .len.
27+
nogrow // the array will never be allowed to grow past `.cap`. set `.nogrow` and `.noshrink` for a truly fixed heap array
28+
nofree // `.data` will never be freed
2729
}
2830

2931
// Internal function, used by V (`nums := []int`)
@@ -133,6 +135,9 @@ fn (mut a array) ensure_cap(required int) {
133135
if required <= a.cap {
134136
return
135137
}
138+
if a.flags.has(.nogrow) {
139+
panic('array.ensure_cap: array with the flag `.nogrow` cannot grow in size, array required new size: ${required}')
140+
}
136141
mut cap := if a.cap > 0 { a.cap } else { 2 }
137142
for required > cap {
138143
cap *= 2
@@ -698,6 +703,9 @@ pub fn (a &array) free() {
698703
// if a.is_slice {
699704
// return
700705
// }
706+
if a.flags.has(.nofree) {
707+
return
708+
}
701709
mblock_ptr := &u8(u64(a.data) - u64(a.offset))
702710
unsafe { free(mblock_ptr) }
703711
}

vlib/builtin/array_shrinkage_test.v renamed to vlib/builtin/array_flags_test.v

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,40 @@ fn test_array_cap_shrinkage_after_deletion() {
5555
assert a.len == 12
5656
assert a.cap == 20
5757
}
58+
59+
fn fixed_array_on_the_heap(len int, size int) []u8 {
60+
data := vcalloc(size)
61+
println(ptr_str(data))
62+
return unsafe {
63+
array{
64+
element_size: 1
65+
len: len
66+
cap: size
67+
data: data
68+
flags: .noshrink | .nogrow | .nofree
69+
}
70+
}
71+
}
72+
73+
fn test_array_fixed_growth() {
74+
mut x := fixed_array_on_the_heap(0, 10)
75+
println(ptr_str(x.data))
76+
x << 5
77+
x << 10
78+
x << 15
79+
x << 20
80+
dump(x)
81+
dump(x.flags)
82+
assert x[2] == 15
83+
assert x.flags == .noshrink | .nogrow | .nofree
84+
}
85+
86+
fn test_array_fixed() {
87+
mut x := fixed_array_on_the_heap(10, 10)
88+
println(ptr_str(x.data))
89+
x[2] = 5
90+
dump(x)
91+
dump(x.flags)
92+
assert x[2] == 5
93+
assert x.flags == .noshrink | .nogrow | .nofree
94+
}

0 commit comments

Comments
 (0)