digitalmars.D.learn - How can I do that in nogc?
- Namespace (9/9) Feb 25 2015 ----
- Ivan Timokhin (3/13) Feb 25 2015 Try
- Namespace (7/20) Feb 25 2015 That seems not to work:
- anonymous (44/53) Feb 25 2015 First of all, if glCheck always uses/evaluates func, then there
- Namespace (3/58) Feb 25 2015 That last thing works. But I have no clue why. o.O
- TheFlyingFiddle (36/38) Feb 25 2015 An alternative solution would be to use function
---- void glCheck(lazy void func, string file = __FILE__, uint line = __LINE__) { func(); glCheckError(file, line); } ---- How can I specify that 'func' is nogc? Or can define the function otherwise?
Feb 25 2015
On Wed, Feb 25, 2015 at 07:32:48PM +0000, Namespace wrote:---- void glCheck(lazy void func, string file = __FILE__, uint line = __LINE__) { func(); glCheckError(file, line); } ---- How can I specify that 'func' is nogc? Or can define the function otherwise?Try void glCheck(scope void delegate() nogc func,...)
Feb 25 2015
On Wednesday, 25 February 2015 at 19:53:16 UTC, Ivan Timokhin wrote:On Wed, Feb 25, 2015 at 07:32:48PM +0000, Namespace wrote:That seems not to work: ---- Error: function test.glCheck (scope void delegate() nogc func, ...) is not callable using argument types (void) -------- void glCheck(lazy void func, string file = __FILE__, uint line = __LINE__) { func(); glCheckError(file, line); } ---- How can I specify that 'func' is nogc? Or can define the function otherwise?Try void glCheck(scope void delegate() nogc func,...)
Feb 25 2015
On Wednesday, 25 February 2015 at 19:32:50 UTC, Namespace wrote:---- void glCheck(lazy void func, string file = __FILE__, uint line = __LINE__) { func(); glCheckError(file, line); } ---- How can I specify that 'func' is nogc? Or can define the function otherwise?First of all, if glCheck always uses/evaluates func, then there is no point in making it lazy. On to the nogc vs. lazy issue. Simpler test case: --- void glCheck(scope lazy int thing) nogc {auto x = thing;} int costly() nogc {return 42;} void main() nogc { glCheck(costly()); /* A */ int x; glCheck(x); /* B */ } --- I guess, the compiler could see that the delegate made for the lazy parameter must be nogc. But it doesn't. So it tries to call a non- nogc delegate in a nogc function which fails of course. You can make the delegate explicit so that you can tag the delegate as nogc yourself: --- void glCheck(scope int delegate() nogc thing) nogc {auto x = thing();} int costly() nogc {return 42;} void main() nogc { glCheck(()=>costly()); int x; glCheck(()=>x); } --- The calls are not as nice, requiring an explicit delegate ("()=>"), but it works. It may be possible to hack through this limitation - NOT THOUGHT-OUT, NOT TESTED, NOT RECOMMENDED: --- void glCheck(scope lazy int thing) nogc; pragma(mangle, glCheck.mangleof) void glCheckImpl(scope int delegate() nogc thing) nogc {auto x = thing();} int costly() nogc {return 42;} void main() nogc { glCheck(costly()); int x; glCheck(x); } ---
Feb 25 2015
On Wednesday, 25 February 2015 at 20:15:10 UTC, anonymous wrote:On Wednesday, 25 February 2015 at 19:32:50 UTC, Namespace wrote:That last thing works. But I have no clue why. o.O Anyway, thanks a lot!---- void glCheck(lazy void func, string file = __FILE__, uint line = __LINE__) { func(); glCheckError(file, line); } ---- How can I specify that 'func' is nogc? Or can define the function otherwise?First of all, if glCheck always uses/evaluates func, then there is no point in making it lazy. On to the nogc vs. lazy issue. Simpler test case: --- void glCheck(scope lazy int thing) nogc {auto x = thing;} int costly() nogc {return 42;} void main() nogc { glCheck(costly()); /* A */ int x; glCheck(x); /* B */ } --- I guess, the compiler could see that the delegate made for the lazy parameter must be nogc. But it doesn't. So it tries to call a non- nogc delegate in a nogc function which fails of course. You can make the delegate explicit so that you can tag the delegate as nogc yourself: --- void glCheck(scope int delegate() nogc thing) nogc {auto x = thing();} int costly() nogc {return 42;} void main() nogc { glCheck(()=>costly()); int x; glCheck(()=>x); } --- The calls are not as nice, requiring an explicit delegate ("()=>"), but it works. It may be possible to hack through this limitation - NOT THOUGHT-OUT, NOT TESTED, NOT RECOMMENDED: --- void glCheck(scope lazy int thing) nogc; pragma(mangle, glCheck.mangleof) void glCheckImpl(scope int delegate() nogc thing) nogc {auto x = thing();} int costly() nogc {return 42;} void main() nogc { glCheck(costly()); int x; glCheck(x); } ---
Feb 25 2015
On Wed, 25 Feb 2015 20:36:32 +0000, Namespace wrote:That last thing works. But I have no clue why. o.O Anyway, thanks a lot!this is a smart hack. that should be NEVER used in production code. anyway, it's good that you don't understand it. your code will crash=20 sooner or later, and you will be forced to remove that trick.=
Feb 25 2015
On Wednesday, 25 February 2015 at 20:46:32 UTC, ketmar wrote:On Wed, 25 Feb 2015 20:36:32 +0000, Namespace wrote:Instead of some wise talk, you could simply explain it. ;) The code is only used for debugging purposes.That last thing works. But I have no clue why. o.O Anyway, thanks a lot!this is a smart hack. that should be NEVER used in production code. anyway, it's good that you don't understand it. your code will crash sooner or later, and you will be forced to remove that trick.
Feb 25 2015
On Wed, 25 Feb 2015 21:32:02 +0000, Namespace wrote:Instead of some wise talk, you could simply explain it. ;)i can, but i certainly don't want to. many people are reading this forum,=20 and i don't want to teach 'em something like this.=
Feb 25 2015
On Wed, 25 Feb 2015 21:32:02 +0000, Namespace wrote:The code is only used for debugging purposes.the best way to make your program undebugable is to use "debugging code=20 that will be turned off in production". this way you aren't debugging the=20 code that will go into production, you debugging something different.=
Feb 25 2015
On Wednesday, 25 February 2015 at 20:36:33 UTC, Namespace wrote:On Wednesday, 25 February 2015 at 20:15:10 UTC, anonymous wrote:[...]I advise you to not use it. It's a hack that relies on implementation details of the compiler. As for how it works: pragma(mangle, ...) sets the mangled name of the following symbol. The mangled name is similar to the "fully qualified name", but it includes parameter types and such. So different overloads of a function have different mangled names, while sharing one fully qualified name. Giving glCheckImpl the same mangled name as glCheck means they then refer to the same code despite having different signatures. This bypasses the type system. DON'T DO THIS. So, whenever glCheck is called, really glCheckImpl is called, and the `scope lazy int` argument is interpreted as a `scope int delegate() nogc` argument. This works, because currently the compiler creates delegates for lazy arguments and calls those delegates when the arguments are accessed. So right now, `lazy int` is the same as `int delegate()` under the hood. But this is not guaranteed. The compiler is free to do this differently. It may depend on compiler flags, etc. SO DON'T DO THIS.It may be possible to hack through this limitation - NOT THOUGHT-OUT, NOT TESTED, NOT RECOMMENDED: --- void glCheck(scope lazy int thing) nogc; pragma(mangle, glCheck.mangleof) void glCheckImpl(scope int delegate() nogc thing) nogc {auto x = thing();} int costly() nogc {return 42;} void main() nogc { glCheck(costly()); int x; glCheck(x); } ---That last thing works. But I have no clue why. o.O Anyway, thanks a lot!
Feb 25 2015
On Wednesday, 25 February 2015 at 19:32:50 UTC, Namespace wrote:How can I specify that 'func' is nogc? Or can define the function otherwise?An alternative solution would be to use function templated on an alias. import std.traits; void glCheck(alias func)(string file = __FILE__, size_t line = __LINE__) nogc if(isCallable!func) { func(); glCheckError(file, line); } void foo() { new int(5); } //Uses GC void bar() nogc { /* ... */ } //Does not use GC unittest { //Calling is a little different glCheck!foo; //Does not compile not nogc glCheck!bar; //Works like a charm. } //If you wanted to take arguments to func //it can be done like this. void glCheck(alias func, string file = __FILE__, size_t line = __LINE__, Args...)(auto ref Args args) nogc if(isCallable!func) { func(args); glCheckError(file, line); } void buz(string a, uint b, float c) nogc { /* ... */ } unittest { //Calling looks like this. glCheck!buz("foobar", 0xBAADF00D, 42.0f); }
Feb 25 2015