Re context variable in callbacks
Johnathan Burchill <[email protected]> Wed, 16 Jun 2004 20:26:49 -0600
| Newsgroups | gmane.comp.sysutils.backup.dar.libdar |
|---|---|
| Message-ID | <[email protected]> |
Hi Denis,
Unfortunately, I only just read your reply to my post! I never got the
reply from sourceforge, even though I was confirmed as a member of the
dar_api mailing list...I only got a message that my post was waiting to be
reviewed by the moderator. Too bad, as I would have liked to have
discussed this further with you before you went ahead with coding.
> Apparently it is standard coding practice for API callback functions to
> accept a "context value", which is a void *, that allows one to use a
> class member function as a callback without resorting to a global
> pointer
> variable.
> Well, to my point of view, after having read the tutorial you give
> reference bellow, there is no standard coding practice that speaks about
> a "context value" for callback. The "context value" is used as a trick
> to make a callback function pointing to non-static member functions of a
> C++ class. The trick implies a static method or normal function to
> explicitely pass the "this" pointer (pointer to the current object which
> is a hidden argument in C++) as explicit argument.
I based that statement on something a professional programmer told me --- I
can only take him at his word. In fact I was not able to find anything in
any reference books on C++ programming that explains context variables for
callback functions. The tutorial is the closest thing I could come up
with.
> Now my question, is do we need libdar calling a non-static member of a
> given object (as callback) ?
As I understand static member functions, you are not allowed to change
their member variables. So in order to return a boolean from the callback,
we need non-static member functions whose variables can be altered. Right?
>First there is a risk, if this objects dies, we will have big problems
>like memory violations. But OK, if you give a wrong argument as address
>of the callback function we get to the same point.
> Second, libdar would always call the method of the same object, and it
> would require first, a way for kdar (for example) to tell libdar which
> object address (the "this" argument) to give to the callback function in
> the "context value".
> Third, logically, it is a class defined in the user application like
>kdar, and libdar does not know anything about this class. This would not
>be very useful to libdar point of view.
I don't understand. Libdar does not understand anything about the regular
callback function either, which is the point of having the callback
function.
>
> As I understand dar, it uses a regular function as the callback.
> Could you
> add perhaps a new set of callback setting functions to the libdar API
>that
> accept a void * context value to be passed. It would be easy to keep
> backwards compatibility with earlier libdar versions by redefining the
> standard callback setting functions to call the new ones with NULL
>for the
> void *.
>Yes, this is still possible.
> I think the need behind is the thread safe libdar library. If the
> library is thread safe, there must not be a function in the API that
> receive the address of a callback function without any context.
> Let"s take an example:
> actually (version 2.1.2 is the last release) libdar API proposes the
> following function:
> set_warning_callback(&my_warning_callback);
>to reach thread safe level, set_warning_callback must have a contextual
>argument, to have a thread discriminant, the callback function stays the
>same. In my idea actually, a possible solution is a new class that will
>gather all static variables that currently make the libdar thread
>unsafe. I have not yet a name for that class, so let"s call it "junk"
>for now. We would then have set_warning_callback a method of the "junk"
>class, and probably any other functions of the current API (op_create,
>etc.)
>Before anything else, each thread should create its own "junk" object
>forcing the calling application to give a thread specific callback
>function in the "junk" constructor.
>OK now, I see, if you have several threads, you could give several
>callback functions (one per thread), but that could lead to some
>ineficiency, you could rather give the same callback function to all
>thread and have an additional argument in the callback prototype that
>tell this common callback function which thread it is called from, and
>which action to do (which object to call, etc...). A void pointer should
>be effectively interesting as it could carry the address to a function
>or the address to an object which method to call.
>
>we would have someting like this:
I'm lost on all of this. I don't know anything yet about making libraries
thread-safe. Is the issue that two instances of a libdar operation,
say isolation and diffing, might try to call the same callback function at
the same time?
> class junk
>{
>public:
> set_warning_callback(void (*callback)(const std::string &x,
> void *context) )
> { warning_callback = callback; };
>set_warning_callback_context_to_give(void *context)
> { context_to_give = context; };
>
> op_create(....);
> op_create_noexcept(...);
> [...]
> private:
> void *context_to_give;
> void (*warning_callback)(const std::string &x, void *context);
>};
>and inside a give thread :
> ...
> junk toto;
> toto.set_warning_callback(&mycallback);
> toto.set_warning_context_to_give(this);
> toto.op_create_noexcept(...);
> ...
>with the global callback function:
> void mycallback(const std::string &x, void *context)
> {
> context->some_method(x);
> // well, this is much simplified.
>}
> Does this makes sens to you ?
Not yet. I have to put some serious thought into all of this. Feels a lot
like you're reinventing the wheel. Unfortunately I'm not much help, and
neither do the texts that I've looked at. Do you know any good books on
C++ library programming that you could point me to?
>
> There is a good tutorial at
> http://www.function-pointer.org/callback.html
> #3: How to Implement Callbacks in C and C++
>
> In the examples given, I currently use method B, but it would be
>better to
> use method A to avoid using the global variable.
>I agree, I dislike global variables.
Glad to see that libdar is on track to be thread-safe.
I updated the cvs, but the docs need some work, so I'll put off the API3
upgrade to KDar until later.
Best regards,
JB
--
Johnathan K. Burchill, Ph.D.
[email protected]
signature.asc
(application/pgp-signature, 189 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (GNU/Linux) iD8DBQBA0QFurXMSOtiWrO4RAqBdAJ9TZTudymm0PCFAt+HgRRBhF+U9KgCg3YIK VP3kAogbPoM784TlluBK8ao= =vVza -----END PGP SIGNATURE-----