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-----