On Saturday, 7 February 2015 at 01:41:19 UTC, Andrei Alexandrescu
wrote:
Consider the previous code:
[...]
static trustedRead(int fildes, void* buf, size_t nbyte)
@trusted
{
return core.sys.posix.unistd.read(fildes, buf, nbyte);
}
static trustedRealloc(void* p, size_t sz, uint ba = 0,
const TypeInfo ti = null) @trusted
{
return GC.realloc(p, sz, ba, ti);
}
static trustedPtrAdd(void[] buf, size_t s) @trusted
{
return buf.ptr+s;
}
static trustedPtrSlicing(void* ptr, size_t lb, size_t ub)
@trusted
{
return ptr[lb..ub];
}
First of all, these little @trusted functions are made obsolete
by the new system. They should certainly be omitted.
@system
{
immutable fd =
core.sys.posix.fcntl.open(name.tempCString(),
core.sys.posix.fcntl.O_RDONLY);
}
Next, you have to realize that @system blocks are like 'try'
blocks: You don't need brackets if there's only one statement in
them.
Here's how I would rewrite what you have written using the new
method:
version (Posix) void[] read(in char[] name, size_t upTo =
size_t.max)
@trusted
{
import core.memory;
// A few internal configuration parameters {
enum size_t
minInitialAlloc = 1024 * 4,
maxInitialAlloc = size_t.max / 2,
sizeIncrement = 1024 * 16,
maxSlackMemoryAllowed = 1024;
// }
@system immutable fd =
core.sys.posix.fcntl.open(name.tempCString(),
core.sys.posix.fcntl.O_RDONLY);
cenforce(fd != -1, name);
scope(exit) core.sys.posix.unistd.close(fd);
stat_t statbuf = void;
@system cenforce(trustedFstat(fd, trustedRef(statbuf)) == 0,
name);
immutable initialAlloc = to!size_t(statbuf.st_size
? min(statbuf.st_size + 1, maxInitialAlloc)
: minInitialAlloc);
void[] result = uninitializedArray!(ubyte[])(initialAlloc);
scope(failure) delete result;
size_t size = 0;
for (;;)
{
@system immutable actual = core.sys.posix.unistd.read(fd,
result.ptr + size, min(result.length, upTo) -
size);
cenforce(actual != -1, name);
if (actual == 0) break;
size += actual;
if (size < result.length) continue;
immutable newAlloc = size + sizeIncrement;
@system result = GC.realloc(
result.ptr, newAlloc, GC.BlkAttr.NO_SCAN)[0 ..
newAlloc];
}
@system return result.length - size >= maxSlackMemoryAllowed
? GC.realloc(result.ptr, size,
GC.BlkAttr.NO_SCAN)[0..size]
: result[0 .. size];
}
Note that I just mechanically your @system blocks with the better
form. I didn't arrange for them to be elegant. There's nothing
wrong with encapsulating a @trusted sequence in a @system block
with brackets, to aid future reviewers in identifying subsequent
code thought to be affected by the @system statements. Also, few
functions will have their @system blocks more or less evenly
distributed throughout like the above function does.
The new proposal will never let you add an unsafe operation
without your knowing it. It's definitely the way forward.