-
-
Save vitalfadeev/2d25724d083a768ae63ab183211c5edc to your computer and use it in GitHub Desktop.
Safe HANDLE for DLang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module safehandle; | |
import core.sys.windows.windows; | |
import std.format; | |
import std.typecons; | |
// Unique_ptr wrapper for WinAPI handles. | |
struct Unique( T, alias DTOR ) | |
{ | |
/** Represents a reference to `T`. Resolves to `T*` if `T` is a value type. */ | |
static if (is(T == class) || is(T == interface)) | |
alias RefT = T; | |
else | |
alias RefT = T*; | |
public: | |
// Deferred in case we get some language support for checking uniqueness. | |
version (None) | |
/** | |
Allows safe construction of `Unique`. It creates the resource and | |
guarantees unique ownership of it (unless `T` publishes aliases of | |
`this`). | |
Note: Nested structs/classes cannot be created. | |
Params: | |
args = Arguments to pass to `T`'s constructor. | |
--- | |
static class C {} | |
auto u = Unique!(C).create(); | |
--- | |
*/ | |
static Unique!T create(A...)(auto ref A args) | |
if (__traits(compiles, new T(args))) | |
{ | |
Unique!T u; | |
u._p = new T(args); | |
return u; | |
} | |
/** | |
Constructor that takes an rvalue. | |
It will ensure uniqueness, as long as the rvalue | |
isn't just a view on an lvalue (e.g., a cast). | |
Typical usage: | |
---- | |
Unique!Foo f = new Foo; | |
---- | |
*/ | |
this(RefT p) | |
{ | |
_p = p; | |
} | |
/** | |
Constructor that takes an lvalue. It nulls its source. | |
The nulling will ensure uniqueness as long as there | |
are no previous aliases to the source. | |
*/ | |
this(ref RefT p) | |
{ | |
_p = p; | |
p = null; | |
assert(p is null); | |
} | |
/** | |
Constructor that takes a `Unique` of a type that is convertible to our type. | |
Typically used to transfer a `Unique` rvalue of derived type to | |
a `Unique` of base type. | |
Example: | |
--- | |
class C : Object {} | |
Unique!C uc = new C; | |
Unique!Object uo = uc.release; | |
--- | |
*/ | |
this(U)(Unique!U u) | |
if (is(u.RefT:RefT)) | |
{ | |
_p = u._p; | |
u._p = null; | |
} | |
/// Transfer ownership from a `Unique` of a type that is convertible to our type. | |
void opAssign(U)(Unique!U u) | |
if (is(u.RefT:RefT)) | |
{ | |
// first delete any resource we own | |
destroy(this); | |
_p = u._p; | |
u._p = null; | |
} | |
~this() | |
{ | |
if (_p !is null) | |
{ | |
DTOR( _p ); | |
destroy(_p); | |
_p = null; | |
} | |
} | |
/** Returns whether the resource exists. */ | |
@property bool isEmpty() const | |
{ | |
return _p is null; | |
} | |
/** Transfer ownership to a `Unique` rvalue. Nullifies the current contents. | |
Same as calling std.algorithm.move on it. | |
*/ | |
Unique release() | |
{ | |
import std.algorithm.mutation : move; | |
return this.move; | |
} | |
/** Forwards member access to contents. */ | |
mixin Proxy!_p; | |
/** | |
Postblit operator is undefined to prevent the cloning of `Unique` objects. | |
*/ | |
@disable this(this); | |
private: | |
RefT _p; | |
} | |
auto CloseHandleWrapper( ref HANDLE h ) | |
{ | |
auto res = CloseHandle( h ); | |
if ( res != 0 ) | |
h = null; // OK | |
if ( res == 0 ) | |
throw new Exception( format!"ERR: %d"( GetLastError() ) ); | |
return res; | |
} | |
//alias SafeHandle = Unique!(void,CloseHandleWrapper); | |
alias SafeHandle = Unique!(void,CloseHandle); | |
// alias SafeHandle = Unique!(void,CloseHandle) | |
// alias Safe_SDL_Window = Unique!(SDL_Window,SDL_DestroyWindow) | |
// alias Safe_SDL_Surface = Unique!(SDL_Surface,SDL_FreeSurface) | |
// alias Safe_SDL_Texture = Unique!(SDL_Texture,SDL_DestroyTexture) | |
// alias Safe_SDL_Renderer = Unique!(SDL_Renderer,SDL_DestroyRenderer) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment