| Thread overview | |||||
|---|---|---|---|---|---|
|
June 14, 2014 Casts and @trusted | ||||
|---|---|---|---|---|
| ||||
This seems to work from quick testing, but it has casts in get_ref that I want to avoid.
cast(T*) refs[i] is obviously not @safe.
cast(T*) _buffer[read].ptr doesn't seem necessary, since _buffer[read] is conceivably a T so _buffer[read].ptr should be a T*. But without it I get "Error: cannot implicitly convert expression (&this._buffer[read]) of type const(char)* to char[5]*"
I do want to pass in a preallocated buffer to store some pointers, at least as one get option. I also want to disallow modification to the ring buffer through those pointers. How might I rework things to enable that usage while being @safe?
enum TakeStrategy { cyclic, once }
alias TS = TakeStrategy;
struct StaticRingBuffer(T, size_t cap) {
static assert (cap > 1);
private T[cap] _buffer;
private size_t _index = cap-1;
private size_t _fill = 0;
@property size_t extra() nothrow const {
return cap-fill;
}
@property size_t index() nothrow const {
return _index;
}
@property size_t fill() nothrow const {
return _fill;
}
@property const ref front() nothrow const {
return _buffer[index];
}
void put(T ele) pure nothrow {
if (index == cap-1) _index = 0;
else ++_index;
_buffer[index] = ele;
if (fill < cap) ++_fill;
}
void put(T[] eles) pure nothrow {
foreach(e; eles) put(e);
}
@trusted void get_ref(TS strat=TS.cyclic)(size_t n, const(T*)[] refs) const nothrow
{
assert(refs.length == n);
static if (strat==TS.once) size_t numreads = fixNToFill(n);
else size_t numreads = n;
size_t read = index;
foreach(i;0..numreads) {
cast(T*) refs[i] = cast(T*) _buffer[read].ptr;
if (read == 0) read = fill-1;
else --read;
}
}
private size_t fixNToFill(size_t n) const nothrow {
return (n > fill) ? fill : n;
}
}
| ||||
June 14, 2014 Re: Casts and @trusted | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Anonymous | On 06/13/2014 06:56 PM, Anonymous wrote:
> @trusted void get_ref(TS strat=TS.cyclic)(size_t n, const(T*)[]
> refs) const nothrow
> {
[...]
> cast(T*) refs[i] = cast(T*) _buffer[read].ptr;
The left-hand side violates a promise: The function takes a slice where the elemenst are const. So, the function says that it will not modify the elements.
Also, _buffer[read] is an element, not a slice:
private T[cap] _buffer;
So, there is no .ptr property.
However, perhaps my test code fails to demonstrate your problem:
auto s = StaticRingBuffer!(int, 10)();
int i;
int*[] arr;
arr ~= &i;
s.get_ref(0, arr);
Please show us complete code. :)
Ali
| |||
June 14, 2014 Re: Casts and @trusted | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | That really is it. The other methods are just other gets to the buffer, like this:
T[] get_dup(TS strat=TS.cyclic)(size_t n) const {
static if (strat==TS.once) size_t numreads = fixNToFill(n);
else size_t numreads = n;
auto ret = new T[](numreads);
size_t read = index;
foreach(i;0..numreads) {
ret[i] = _buffer[read].dup;
if (read == 0) read = fill-1;
else --read;
}
return ret;
}
But ah, the .ptr property is not supposed to work for array element? In any case it still works as cast(T*) &(_buffer[read]). Here's the unittest I slapped together:
unittest {
char[5] hello = "hello";
char[5] world = "world";
char[5] forty = "forty";
char[5] three = "three";
char[5] gdbye = "gdbye";
alias chars_t = char[5];
chars_t[] foo = [hello,world,forty,three];
chars_t[] oob = foo.dup.reverse;
StaticRingBuffer!(chars_t,4) bar;
bar.put(foo);
assert(bar.index==3);
const(chars_t)*[4] ptrs;
bar.get_ref(4,ptrs);
assert(bar.get_dup(4) == oob);
foreach(i,ptr; ptrs) assert(*ptr == oob[i]);
assert(bar.get_dup(7) == [three,forty,world,hello,three,forty,world]);
bar.put("gdbye");
assert(bar.index==0);
assert(bar.get_dup(4) == [gdbye,three,forty,world]);
assert(bar.get_dup(7) == [gdbye,three,forty,world,gdbye,three,forty]);
}
But now I see my problem is that a simple const(T*)[N] already initializes its elements to null, so nothing past that should modify them. And without the casts, the type on &(_buffer[read]) is a const(T*) instead of something else which finally makes sense. Somehow I thought .ptr was a property of everything.
And now I realize that I can just put the ptr array within the get scope, and return it, to initialize a lhs const(T*)[] by value. I was making things hard on myself by trying to modify a passed-in buffer.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply