www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - automatic function call after closing block

reply "Saaa" <empty needmail.com> writes:
I'd like the following:

texture.bind() //class texture, method bind.
{
    ..
} //here texture.unbind would automatically be run.

Is this possible?
Sep 20 2008
next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sat, 20 Sep 2008 20:15:17 +0400, Saaa <empty needmail.com> wrote:

 I'd like the following:

 texture.bind() //class texture, method bind.
 {
     ..
 } //here texture.unbind would automatically be run.

 Is this possible?

Yep! texture.bind() { scope(exit) texture.unbind() ... }
Sep 20 2008
next sibling parent reply "Saaa" <empty needmail.com> writes:
Ah, that's at least nicer, but I meant that I somehow change texture.bind() 
to include texture.unbind()

class texture
{
public void bind()
{
    ..
    underlying scope(exit) texture.unbind()
}

private void unbind()
{
    ..
}

}


..
texture.bind()
{
    ..
}
..


 Yep!

 texture.bind()
 {
    scope(exit) texture.unbind()
    ...
 } 

Sep 20 2008
next sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Saaa <empty needmail.com> wrote:
 Ah, that's at least nicer, but I meant that I somehow change texture.bind() 
 to include texture.unbind()

You can do something very similar: class Texture { public void bind(void delegate() body) { // bind a texture here body(); unbind(); } private void unbind() { // unbind the texture here } } texture.bind( { // use the bound texture here } );
Sep 20 2008
prev sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
As to how it works.  The t.bindBlock() in {...} can be rewritten using 
C++-like syntax:

void worker()
{
    // some rendering code!
}
BindBlock bb = t.bindBlock();
bb.opIn(&worker);

The code below simply writes all this in one line using a temporary 
BindBlock structure, an overloaded operator 'in', and an inline 
anonymous delegate syntax.

Saaa <empty needmail.com> wrote:
 :D
 Looks cool!
 No way I could have come up with that.
 Same question (as I have no clue how this internally works):
 Is there a performance penalty?
 
 How about a horrible/wonderful misuse of the 'in' operator?  (credited
 to Tom S):

 class Texture
 {
 ...
    struct BindBlock
    {
        Texture self;
        void opIn(void delegate() dg)
        {
            self.bind();
            scope(exit) self.unbind();
            dg();
        }
    }

    BindBlock bindBlock() { return BindBlock(this); }
 ...
 }

 auto t = new Texture("foo.png");

 t.bindBlock() in
 {
    // some rendering code!
 };


Sep 20 2008
prev sibling next sibling parent reply "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sat, Sep 20, 2008 at 12:24 PM, Saaa <empty needmail.com> wrote:
 Ah, that's at least nicer, but I meant that I somehow change texture.bind()
 to include texture.unbind()

 class texture
 {
 public void bind()
 {
    ..
    underlying scope(exit) texture.unbind()
 }

 private void unbind()
 {
    ..
 }

 }


 ..
 texture.bind()
 {
    ..
 }
 ..


 Yep!

 texture.bind()
 {
    scope(exit) texture.unbind()
    ...
 }


How about a horrible/wonderful misuse of the 'in' operator? (credited to Tom S): class Texture { ... struct BindBlock { Texture self; void opIn(void delegate() dg) { self.bind(); scope(exit) self.unbind(); dg(); } } BindBlock bindBlock() { return BindBlock(this); } ... } auto t = new Texture("foo.png"); t.bindBlock() in { // some rendering code! }; It has a nice functional-sounding flair to it, with the 'in' there ;)
Sep 20 2008
parent "Saaa" <empty needmail.com> writes:
:D
Looks cool!
No way I could have come up with that.
Same question (as I have no clue how this internally works):
Is there a performance penalty?

 How about a horrible/wonderful misuse of the 'in' operator?  (credited
 to Tom S):

 class Texture
 {
 ...
    struct BindBlock
    {
        Texture self;
        void opIn(void delegate() dg)
        {
            self.bind();
            scope(exit) self.unbind();
            dg();
        }
    }

    BindBlock bindBlock() { return BindBlock(this); }
 ...
 }

 auto t = new Texture("foo.png");

 t.bindBlock() in
 {
    // some rendering code!
 };


 It has a nice functional-sounding flair to it, with the 'in' there ;) 

Sep 20 2008
prev sibling next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sat, Sep 20, 2008 at 1:48 PM, Saaa <empty needmail.com> wrote:
 :D
 Looks cool!
 No way I could have come up with that.
 Same question (as I have no clue how this internally works):
 Is there a performance penalty?

No more than any other method that uses delegates; it's just a bit of syntax abuse to call a function. Delegates work by passing an implicit context pointer to the nested function as a parameter. Nested functions use a pointer to the stack frame of the enclosing function as the context pointer, so they can access the local variables of the enclosing function. There is a performance penalty for calling delegates just as there is for calling functions through function pointers: it may cause a processor pipeline stall. However with the preponderance of object-oriented programming in which calling virtual methods involves calling functions through pointers, many modern processors have been so heavily optimized for it that the performance difference from hard-coding the function address into the code is negligible. Not nonexistent, but definitely better than it used to be. And besides -- you're calling that delegate once, so it'll be just a constant time overhead.
Sep 20 2008
prev sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sat, Sep 20, 2008 at 2:40 PM, Jarrett Billingsley
<jarrett.billingsley gmail.com> wrote:
 On Sat, Sep 20, 2008 at 1:48 PM, Saaa <empty needmail.com> wrote:
 :D
 Looks cool!
 No way I could have come up with that.
 Same question (as I have no clue how this internally works):
 Is there a performance penalty?

No more than any other method that uses delegates; it's just a bit of syntax abuse to call a function. Delegates work by passing an implicit context pointer to the nested function as a parameter. Nested functions use a pointer to the stack frame of the enclosing function as the context pointer, so they can access the local variables of the enclosing function. There is a performance penalty for calling delegates just as there is for calling functions through function pointers: it may cause a processor pipeline stall. However with the preponderance of object-oriented programming in which calling virtual methods involves calling functions through pointers, many modern processors have been so heavily optimized for it that the performance difference from hard-coding the function address into the code is negligible. Not nonexistent, but definitely better than it used to be. And besides -- you're calling that delegate once, so it'll be just a constant time overhead.

I suppose I should also mention that if you're using D2, delegates will secretly allocate outer functions' local variables on the heap if nested functions access them. There is currently no way in D2 to achieve the efficient D1 behavior of always keeping the stack frame on the stack.
Sep 20 2008
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2008-09-20 12:15:17 -0400, "Saaa" <empty needmail.com> said:

 I'd like the following:
 
 texture.bind() //class texture, method bind.
 {
     ..
 } //here texture.unbind would automatically be run.
 
 Is this possible?

You could create a scope class, bind in the constructor and unbind in the destructor. Something like this: scope class Binding { Texture t; this(Texture t) { this.t = t; t.bind() }; ~this() { t.unbind(); } } then use it like this: { scope b = new Binding(texture); ... // automatic destruction of b; } Perhaps it could be made more elegant in D2 with struct destructors. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 20 2008
parent "Saaa" <empty needmail.com> writes:
Never used/heart of a scope class, thanks!
But I'll try the delegate thing first ;)


 I'd like the following:

 texture.bind() //class texture, method bind.
 {
     ..
 } //here texture.unbind would automatically be run.

 Is this possible?

You could create a scope class, bind in the constructor and unbind in the destructor. Something like this: scope class Binding { Texture t; this(Texture t) { this.t = t; t.bind() }; ~this() { t.unbind(); } } then use it like this: { scope b = new Binding(texture); ... // automatic destruction of b; } Perhaps it could be made more elegant in D2 with struct destructors. -- Michel Fortin michel.fortin michelf.com http://michelf.com/

Sep 20 2008
prev sibling next sibling parent Frank Benoit <keinfarbton googlemail.com> writes:
Saaa schrieb:
 I'd like the following:
 
 texture.bind() //class texture, method bind.
 {
     ..
 } //here texture.unbind would automatically be run.
 
 Is this possible?
 
 
 
 

void bind( Texture t, void delegate() dg ){ t.bind(); dg(); t.unbind(); } bind( texture, { ... });
Sep 20 2008
prev sibling next sibling parent "Saaa" <empty needmail.com> writes:
Delegate it is then.
Is there any performance penalty when using delegates? 
Sep 20 2008
prev sibling next sibling parent reply "Saaa" <empty needmail.com> writes:
These performance questions of mine are more questions in how the mechanism 
works than that I worry about the speed. 
Sep 20 2008
parent Christopher Wright <dhasenan gmail.com> writes:
Saaa wrote:
 These performance questions of mine are more questions in how the mechanism 
 works than that I worry about the speed. 

Delegate performance should be no worse than virtual method invocation. You're passing a pointer to a function, whereas virtual method invocation is effectively passing a pointer to a pointer to a function.
Sep 20 2008
prev sibling parent "Saaa" <empty needmail.com> writes:
Thanks all! 
Sep 21 2008