[sane-devel] SANE V2

Matto Marjanovic maddog@mir.com
Mon, 9 Dec 2002 16:39:54 -0500

 >From: Diego Zuccato <diego@otello.alma.unibo.it>
 >Date: Mon, 09 Dec 2002 00:13:01 +0000
 >Henning Meier-Geinitz wrote:
 >> And this would be returned by any SANE API function that currently
 >> returns SANE_Status? Nice, because it links the error number and the
 >> message. No need for an extra call to a function.
 >Yep. That's why I like this method. :-)

(For those who've lost track:  "this method" is to use struct, containing
 both the status code and a verbose string pointer, as the return value of
 all the sane_() functions.)

Um, except now a string has to be marshalled over the network every time
 a sane function is called, and reconstructed on the client side even if
 it isn't used.

 >> Yet another way would be to use an additional callback:
 >Callbacks always give me nightmares (I'm developing a db async access
 >infrastructure that interacts with gtk... brr!)

A true asynchronous callback cannot be used with the network protocol.
However, it can work in this case:
  o Frontend calls sane_func(), hands its callback to network backend.
  o Net backend signals remote net frontend "execute sane_func()".
  o Remote network frontend calls sane_func(), hands its callback to backend.
  o Backend calls network callback to put a string somewhere on remote side.
  o Remote network frontend sends that string back along with the response
     to "sane_func()" request.
  o Network backend calls the client frontend's callback with string,
     then finally returns from "sane_func()" request.

But this has pretty much all the same problems and lack of benefits as
 the above method.

 >> The really interesting error messages are the dynamic ones: "Couldn't
 >> open %s". And %s can be anything and can change multiple times between
 >> sane_init and sane_exit.
 >Err... I didn't think about these. :-(
 >Well, in that case, use the strdup() technique: the called function
 >allocates the needed memory that must be freed by the caller. I heard
 >(well, seen in some code) that that could be a problem under winkozz,
 >since if a dll allocates memory, that memory must be freed from the dll
 >itself. Just add a free() wrapper in the dll code... May be SANE_free()

What a pain....
Now I have to call some version of free() (either SANE's or just libc's)
 everytime I call a sane_function()!!!

I much prefer Henning's original idea, as follows:

Threading is not a very big issue for SANE.
>From the perspective of a single device handle, most of the API is
 synchronous and leaves no room for threading anyway --- except for

That is to say, I am not allowed to call a second sane_func(H, ...) on the
 same device handle H while another sane_func(H, ...) is still executing.
 (Except for sane_cancel() --- I had some remarks about this a while ago,
 too; I'll try to find them.)

That means that the current error state, per device handle, is well-defined
 at all times.  So, I don't see any problems with Henning's original idea:

 >> > SANE_String_Const sane_verbose_error(Sane_Handle h)
 >> >
 >"This function provides a verbose description of the error code
 >returned by the latest call to a SANE function. The returned ...
 >So the intention is: the message stays the same until any other
 >SANE function returns an non-error status code. Everything not
 >returning a status would be ignored.

This function always provides the error "when the error occurs", because
 it is called after one sane_func(H) and before the next sane_func(H).

The string pointer returned by this function should be valid until the
 next sane_function(H) is called on the same device handle.  This is 
 important to maintain thread-safety over multiple devices.

The string is, however, "owned" by the backend, which is free to overwrite
 it, free() it, etc., during the next sane_func(H) call.

The backend can allocate/write this string anyway it wants, and no one
 else has to deal with it until the frontend explicitly asks for it.

-matt "keepin' it real (simple)" m.