Marking its various bits as @nogc is still proving to be a challenge
since Object.destroy is not @nogc, among other things.
We _are_ using GC.addRange and GC.removeRange to handle anything
inside the underlying type that uses GC.
Why the user would do this in conjunction with Unique is
questionable, but until we can explicitly forbid doing so, let's
not break garbage collection for them.
Note that this also makes nested structs and classes impossible,
because there is no way AFAIK to get the frame pointer into
unique()
Also cleaned up the Unique documentation a bit.
Unfortunately some of the unittests could not be used as documented
unittests because placing them in the struct gives an error about
RTInfo!(Nested) being recursvely expanded.
- add RefCounted!T.this(T) which takes an RValue or a copy
and use move to initialized the refcounted store
- add refCounted to infer T from the argument and disable
RefCounted's autoInit, also move initializes the store
From the related pull request
(https://github.com/D-Programming-Language/phobos/pull/3139),
there seems to be a general consensus that it is more important to
do Unique "right", even if that means breaking changes, so long as
there is a clean migration path. With that in mind, I have made the
following additional changes:
- Instead of constructors that take a RefT, Uniques can now be
created one of two ways: via .create or .fromNested.
See the DDocs of both for details.
- opDot is replaced with "alias _p this". A cursorty Google search
indicates that opDot is deprecated and that alias this is the
preferred method. Like C++'s unique_ptr, Unique now enjoys
pointer-like operations (such as dereferencing),
but cannot be set to null or assigned from a different pointer
due to opAssign and the disabled postblit constructor.
- Consequently, isEmpty has been removed. Instead, just use
is null as you would with a pointer.
- Removal of redundant unit tests
- Various comment and unit test cleanup
It is currently impossible (or so it seems) to use malloc and
emplace to create a nested class or struct, so we'll return to
using the GC for now. We'll also restore the constructors that take
a RefT, as using new _inside_ the context of the nested class or
struct is apparently the only way to create one currently.
I picked up the trick of converting a pointer into an array
using the [0 .. size] syntax from std/regex/package.d.
Unique.create is still segfaulting, but this seems to be an issue
with the class version of emplace regardless of this Unique work.
The bug can be found here:
https://issues.dlang.org/show_bug.cgi?id=14402
Whenever D is brought up to the general programming public,
the garbage collector is quickly raised as a point of contention.
Regardless of how legitimate or well-informed these concerns are,
it would be a massive public relations boon --- and great for the language,
to boot --- if we could trot out a solid said of RAII-based smart pointers
for those who prefer to use them. We have a solid start in
std.typecons.Unique and std.typecons.RefCounted.
Unfortunately, these classes seem to be victims of bit rot and
compiler bugs of days long gone.
An overview of the changes in this commit is as follows:
- Unique's underlying data now uses malloc and free
instead of the garbage collector. Given that many people use RAII
smart pointers to escape the GC, it seems to make more sense to
avoid it here. On a related note, isn't delete deprecated?
The current destructor uses it.
- std.algorithm.move is used instead of a special release
member function. Whether by design or by happy accident,
move transfers ownership between Unique pointers in a very
similar manner to C++'s std::move with std::unique_ptr.
Along with being a familiar paradigm to C++ users,
using move to transfer ownership makes more intuitive sense
and builds consistency with the rest of Phobos.
- With std.algorithm.move transferring ownership, release now just
frees the underlying pointer and nulls the Unique.
- Unique.create is no longer compiled out using version(None).
Regardless of whether or not there is language support for
checking uniqueness, a utility function that creates a Unique,
taking the same arguments as the underlying type's constructor,
is extremely useful, as demonstrated by the addition of
make_unique to C++14.
- Because Unique.create is now in place and Unique is backed with
malloc, constructors taking a pointer have been removed.
This encourages the use of create as the idiomatic,
consistent method to, well, create Unique objects.
If one can only get a Unique by calling create or moving another
into it, we also ensures uniqueness in one fell swoop.
- A new method, get, returns the underlying pointer, for use in
functions and code that do not play a role in the life cycle
of the object. Smart pointers are as much about ownership
semantics as they are about allocating and freeing memory,
and non-owning code should continue to refer to data using a raw
pointer or a reference.