[Home]  [Edit this page]  [Recent Changes]  [Special Pages]  [Help
QbasicFAQ_ChangeColors » iTV » MUMPS » QbasicFAQ_Inkey » CPU » help » complexnumbers » CppCli » WhatLinksHere » QbasicFAQ_EventDriven » thunks
Displaying differences between revision 11 and the latest revision


Some libraries, like sax, may take a function as an argument with one less parameter than you need. Expat, a sax implementation for XML http://expat.sourceforge.net/ , for example, takes global function pointers as the callback argument. This can be annying if you want a reentrant parser. ¶

How you can associate the callback function with an instance of an object if you are using the same parser from different threads, or how can you avoid global variables?¶

It is possible using a thunk technique.¶

Suppose you wanted all your callbacks to reference a class or struct:¶

[code]struct CallbackHelper¶

//a bunch of variables ...¶
}[/code]¶

and your api requires a callback like this¶

[code]typedef void (*callback)(int callback_supplied1,¶
double callback_supplied2)[/code]¶

but you need a CallbackHelper passed to your version:¶

[code]typedef void (*Mycallback)(int callback_supplied1,¶
double callback_supplied2, CallbackHelper *myObject)[/code]¶

Many languages provide a nice way to do this with a closure or partial application or lambda lifting. Haskell, emacs lisp, Ruby, python, and many more have decent support for this case. ¶

For languages that don't, you have to create a callback object which pushes the extra argument on the stack and then continues on to the real callback. ¶

C and C++ are lacking in built in support, but there is a workaround. Create a thunk, an intermediate callback, that pushes your hidden argument onto the stack and calls your final callback. You have to create a thunk for each function you want called back to which you want to supply extra arguments.¶

1. Create a space for the thunk. The best place is within CallbackHelper¶
[code]struct CallbackHelper¶

// a bunch of variables¶
...¶
//space for the thunk¶
unsigned thunk[16]; //whatever, just make sure its enough.¶
}[/code]¶

2. write your callback including y
our CallbackHelper¶
[code]static
void myCallback(int callback_supplied1, double callback_supplied2,¶
CallbackHelp
er *me);[/code]¶

3. Create
the thunk, usally with a macro or other function.¶
[code]thunk
[0]=push &myCallbackHelper //according to your instruction set¶
thunk
[1]=jump myCallback //according to your instruction set[/code]¶
If you have a
protected memory operating system, like Windows NT/XP/9X/2K, you have to make sure the thunk is executable. The virtual memory functions in windows allow this to be done quite easily.[br]¶
You can replace the jump myCallback with a callMyCallback;return if you need to do something more involved with the arg
uments (reorder them etc).[br]¶

4. Register the callbac
k. ¶
[code
]//coerce thunk into the right type.¶
callback callWithMyStructure=(callback)(thunk);¶
//register with the underlying library¶
CallMeBackWithSomethingUseful(callWithMyStructure)[/code
]

5. Be careful.¶

Don't delete the thunk until there are no more references to it. If you delete your callback object and then dereference it, you are asking for a crash whether or not you are using thunk techniques. ¶

However, with the thunk techniuqe, if you have destroyed the thunk and it gets called back from somewhere, not only will you crash, but you will be wondering why your instruction pointer is in your data space.¶

Although this is an unusual technique, it is not especially dangerous and is something libraries you may be using already do, maybe your tcp/IP stack or embedded OS. Certainly, its nothing more complicated than what your compiler does -- its pretty bogus there is no partial application built into C, but you can roll your own when you need to.¶

The Active Template Library (ATL) for windows COM program does exactly the above technique to create a function call that can invoke an instance method on a class. It does this because window classes in ATL are classes, and windows callbacks for particular windows messages are static functions
.



last edited (March 3, 2007) by bilderbikkel, Number of views: 43739, Current Rev: 12 (Diff)

[Edit this page]  [Page history]  [What links here]  [Discuss this topic]  [Printer Friendly]  
© 1996-2008 Community Networks Ltd. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited. Violators of this policy may be subject to legal action. Please read Terms Of Use and Privacy Statement for more information. Site Management by Lars Hagelin at Kontantkort.se.