Skip to content

Commit 27a1553

Browse files
authored
Merge pull request #4832 from nordlow/pure-refcounted
std.typecons: Make RefCounted pure nothrow @nogc when possible
2 parents d34668d + ddebfaf commit 27a1553

File tree

1 file changed

+31
-18
lines changed

1 file changed

+31
-18
lines changed

std/typecons.d

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5082,9 +5082,17 @@ struct RefCounted(T, RefCountedAutoInitialize autoInit =
50825082
RefCountedAutoInitialize.yes)
50835083
if (!is(T == class) && !(is(T == interface)))
50845084
{
5085+
extern(C) private pure nothrow @nogc static // TODO remove pure when https://issues.dlang.org/show_bug.cgi?id=15862 has been fixed
5086+
{
5087+
pragma(mangle, "free") void pureFree( void *ptr );
5088+
pragma(mangle, "gc_addRange") void pureGcAddRange( in void* p, size_t sz, const TypeInfo ti = null );
5089+
pragma(mangle, "gc_removeRange") void pureGcRemoveRange( in void* p );
5090+
}
5091+
50855092
/// $(D RefCounted) storage implementation.
50865093
struct RefCountedStore
50875094
{
5095+
import core.memory : pureMalloc;
50885096
private struct Impl
50895097
{
50905098
T _payload;
@@ -5096,31 +5104,27 @@ if (!is(T == class) && !(is(T == interface)))
50965104
private void initialize(A...)(auto ref A args)
50975105
{
50985106
import core.exception : onOutOfMemoryError;
5099-
import core.memory : GC;
5100-
import core.stdc.stdlib : malloc;
51015107
import std.conv : emplace;
51025108

5103-
_store = cast(Impl*)malloc(Impl.sizeof);
5109+
_store = cast(Impl*)pureMalloc(Impl.sizeof);
51045110
if (_store is null)
51055111
onOutOfMemoryError();
51065112
static if (hasIndirections!T)
5107-
GC.addRange(&_store._payload, T.sizeof);
5113+
pureGcAddRange(&_store._payload, T.sizeof);
51085114
emplace(&_store._payload, args);
51095115
_store._count = 1;
51105116
}
51115117

51125118
private void move(ref T source)
51135119
{
51145120
import core.exception : onOutOfMemoryError;
5115-
import core.memory : GC;
5116-
import core.stdc.stdlib : malloc;
51175121
import core.stdc.string : memcpy, memset;
51185122

5119-
_store = cast(Impl*)malloc(Impl.sizeof);
5123+
_store = cast(Impl*)pureMalloc(Impl.sizeof);
51205124
if (_store is null)
51215125
onOutOfMemoryError();
51225126
static if (hasIndirections!T)
5123-
GC.addRange(&_store._payload, T.sizeof);
5127+
pureGcAddRange(&_store._payload, T.sizeof);
51245128

51255129
// Can't use std.algorithm.move(source, _store._payload)
51265130
// here because it requires the target to be initialized.
@@ -5233,11 +5237,10 @@ to deallocate the corresponding resource.
52335237
.destroy(_refCounted._store._payload);
52345238
static if (hasIndirections!T)
52355239
{
5236-
import core.memory : GC;
5237-
GC.removeRange(&_refCounted._store._payload);
5240+
pureGcRemoveRange(&_refCounted._store._payload);
52385241
}
5239-
import core.stdc.stdlib : free;
5240-
free(_refCounted._store);
5242+
5243+
pureFree(_refCounted._store);
52415244
_refCounted._store = null;
52425245
}
52435246

@@ -5322,7 +5325,7 @@ assert(refCountedStore.isInitialized)).
53225325
}
53235326

53245327
///
5325-
@system unittest
5328+
pure @system nothrow @nogc unittest
53265329
{
53275330
// A pair of an $(D int) and a $(D size_t) - the latter being the
53285331
// reference count - will be dynamically allocated
@@ -5336,7 +5339,7 @@ assert(refCountedStore.isInitialized)).
53365339
// the pair will be freed when rc1 and rc2 go out of scope
53375340
}
53385341

5339-
@system unittest
5342+
pure @system unittest
53405343
{
53415344
RefCounted!int* p;
53425345
{
@@ -5375,7 +5378,7 @@ assert(refCountedStore.isInitialized)).
53755378
assert(a.x._refCounted._store._count == 2, "BUG 4356 still unfixed");
53765379
}
53775380

5378-
@system unittest
5381+
pure @system nothrow @nogc unittest
53795382
{
53805383
import std.algorithm.mutation : swap;
53815384

@@ -5384,7 +5387,7 @@ assert(refCountedStore.isInitialized)).
53845387
}
53855388

53865389
// 6606
5387-
@safe unittest
5390+
@safe pure nothrow @nogc unittest
53885391
{
53895392
union U {
53905393
size_t i;
@@ -5399,7 +5402,7 @@ assert(refCountedStore.isInitialized)).
53995402
}
54005403

54015404
// 6436
5402-
@system unittest
5405+
@system pure unittest
54035406
{
54045407
struct S { this(ref int val) { assert(val == 3); ++val; } }
54055408

@@ -5408,7 +5411,15 @@ assert(refCountedStore.isInitialized)).
54085411
assert(val == 4);
54095412
}
54105413

5411-
@system unittest
5414+
// gc_addRange coverage
5415+
@system pure unittest
5416+
{
5417+
struct S { int* p; }
5418+
5419+
auto s = RefCounted!S(null);
5420+
}
5421+
5422+
@system pure nothrow @nogc unittest
54125423
{
54135424
RefCounted!int a;
54145425
a = 5; //This should not assert
@@ -5417,6 +5428,8 @@ assert(refCountedStore.isInitialized)).
54175428
RefCounted!int b;
54185429
b = a; //This should not assert either
54195430
assert(b == 5);
5431+
5432+
RefCounted!(int*) c;
54205433
}
54215434

54225435
/**

0 commit comments

Comments
 (0)