Dynamic array as stack and GC.BlkAttr.APPENDABLE
IgorStepanov via Digitalmars-d
digitalmars-d at puremagic.com
Sat Nov 15 14:40:02 PST 2014
On Saturday, 15 November 2014 at 03:41:56 UTC, Steven
Schveighoffer wrote:
> On 11/14/14 8:56 PM, IgorStepanov wrote:
>> On Friday, 14 November 2014 at 23:49:00 UTC, ketmar via
>> Digitalmars-d
>> wrote:
>>> On Fri, 14 Nov 2014 23:23:17 +0000
>>> IgorStepanov via Digitalmars-d <digitalmars-d at puremagic.com>
>>> wrote:
>>>
>>>> What does the NO_INTERIOR flag?
>>> it stops GC to acknowledge pointers inside allocated area as
>>> anchors.
>>> i.e. if there is no pointer to the head (first address) of
>>> allocated
>>> memory, it is assumed to be garbage.
>>>
>>> this way we have much less "false pointers", and GC not doing
>>> pointer->block conversions.
>>>
>>> for buckets we certainly has "head pointer" and can't have
>>> pointers to
>>> bucket elements without "head pointer". so it's safe to tell
>>> GC that it
>>> shouldn't do unnecessary work.
>>
>> In other words, if buckets array will contain only uint-s
>> there is no
>> reason to mark buckets with NO_INTERIOR?
>
> In case ketmar's reply doesn't drive it home...
>
> NO_INTERIOR means that the GC should NOT consider pointers to a
> block as valid references if those pointers don't point to the
> HEAD of the block. In other words, they point to the interior.
>
> An example
>
> int * x = new int;
> *x = 5;
> byte *b = cast(byte *)x;
> b++; // b is now an interior pointer, yet x is not.
>
> If we had marked x's block as NO_INTERIOR, we are fine as long
> as x remains. If we set x to null, there is a danger that the
> block is collected, and now b is dangling.
>
> Now, this isn't a whole lot more efficient, you still have to
> look up what b points at and see that it has the flag set. BUT,
> where it DOES help is if you had some size_t somewhere on a
> stack, that happens to be the same value as b, the GC may think
> it's a pointer, but correctly not keep the block alive just for
> that "false pointer". The larger the block, the more helpful
> NO_INTERIOR is.
>
> -Steve
Thanks for explanations. I undersood that now. However I have got
a strange bug with NO_INTERIOR.
I have the following function:
static Bucket[] newBuckets(in size_t len) @trusted pure nothrow
{
Bucket[] ret = new Bucket[len];
if (!__ctfe)
{
GC.setAttr(ret.ptr, GC.BlkAttr.NO_INTERIOR);
}
return ret;
}
The Bucket declaration has a two uint fields and one of those has
a explicit initializer:
private enum uint EmptyBucket = uint.max;
static struct Bucket
{
uint depth;
uint index = EmptyBucket;
@property bool occupied() const
{
return index != EmptyBucket;
}
}
I call this function for creating new bucket array (in init()
function, at first value inserting and at rehashing).
I don't create a copy, slice, I don't get a array pointer. Before
array creating and rehashing I use buckets only for access by
index. However I have got a error, when `index` field initializes
with some strange value when newBuckets argument is very big.
(buckets.length is big value). When I comment a
GC.setAttr(ret.ptr, GC.BlkAttr.NO_INTERIOR); line, code start
works fine.
Do I any fundamental error in this code?
May be Bucket[] ret = new Bucket[len]; ret.ptr is not base
pointer?
More information about the Digitalmars-d
mailing list