www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How can I do that in nogc?

reply "Namespace" <rswhite4 gmail.com> writes:
----
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
next sibling parent reply Ivan Timokhin <timokhin.iv gmail.com> writes:
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
parent "Namespace" <rswhite4 gmail.com> writes:
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:
 ----
 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,...)
That seems not to work: ---- Error: function test.glCheck (scope void delegate() nogc func, ...) is not callable using argument types (void) ----
Feb 25 2015
prev sibling next sibling parent reply "anonymous" <anonymous example.com> writes:
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
parent reply "Namespace" <rswhite4 gmail.com> writes:
On Wednesday, 25 February 2015 at 20:15:10 UTC, anonymous wrote:
 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); } ---
That last thing works. But I have no clue why. o.O Anyway, thanks a lot!
Feb 25 2015
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
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
parent reply "Namespace" <rswhite4 gmail.com> writes:
On Wednesday, 25 February 2015 at 20:46:32 UTC, ketmar wrote:
 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 sooner or later, and you will be forced to remove that trick.
Instead of some wise talk, you could simply explain it. ;) The code is only used for debugging purposes.
Feb 25 2015
next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
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
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
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
prev sibling parent "anonymous" <anonymous example.com> writes:
On Wednesday, 25 February 2015 at 20:36:33 UTC, Namespace wrote:
 On Wednesday, 25 February 2015 at 20:15:10 UTC, anonymous wrote:
[...]
 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!
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.
Feb 25 2015
prev sibling parent "TheFlyingFiddle" <kurtyan student.chalmers.se> writes:
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