Can assumeSafeAppend() grab more and more capacity?
Ali Çehreli via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Mon Jun 5 14:08:21 PDT 2017
Imagine an array that wants to reuse its buffer after removing elements
from it. For example, a PID waiting list can remove completed elements
and add new ones at the end.
The code would call assumeSafeAppend like this:
arr = arr.remove!(e => e % 2);
arr.assumeSafeAppend();
1) Assuming that the array is not relocated, is it possible that the
capacity will grow and grow? (Imagine that a new memory page from the GC
beyond the current capacity becomes available? Would assumeSafeAppend()
grab that as capacity as well?)
For example, if capacity was non-zero before the two lines above, would
that assumeSafeAppend() call find more capacity than before?
2) If so, is the capacity "allocated" for this buffer or can the GC use
those pages for other purposes, effectively reducing the array's capacity?
In other words, is having capacity a guarantee like having called reserve()?
3) Bonus: Shouldn't the array specialization of std.algorithm.remove
call assumeSafeAppend if the array has capacity to begin with? (The
equivalent of following code?)
const oldCap = arr.capacity;
// ... do std.algorithm.remove magic on arr ...
if (oldCap) {
arr.assumeSafeAppend();
}
I'm aware that there can be multiple slices with non-zero capacity until
one of them grabs the capacity for itself but it's ok for remove() to
give the capacity to just one of them.
Here is a test program that plays with this idea, starting with two
identical slices with same capacity:
import std.stdio;
import std.array;
import std.algorithm;
void myRemove(ref int[] arr) {
const cap = arr.capacity;
arr = arr.remove!(e => e % 2);
if (cap) {
arr.assumeSafeAppend();
}
}
void info(arrays...)(string title) {
writefln("\n%s", title);
foreach (i, arr; arrays) {
writefln(" %s - ptr: %s, len: %s, cap: %s",
(arrays[i]).stringof, arr.ptr, arr.length, arr.capacity);
}
}
void main() {
auto a = [ 1, 2, 3, 4 ];
auto b = a;
info!(a, b)("before myRemove(a)");
myRemove(a);
info!(a, b)("after myRemove(a)");
myRemove(b);
info!(a, b)("after myRemove(b)");
}
before myRemove(a)
a - ptr: 7F15F40D4060, len: 4, cap: 7
b - ptr: 7F15F40D4060, len: 4, cap: 7
after myRemove(a)
a - ptr: 7F15F40D4060, len: 2, cap: 7 <== 'a' grabbed capacity
b - ptr: 7F15F40D4060, len: 4, cap: 0 <==
after myRemove(b)
a - ptr: 7F15F40D4060, len: 2, cap: 7
b - ptr: 7F15F40D4060, len: 3, cap: 0
Ali
More information about the Digitalmars-d-learn
mailing list