[sane-devel] SANE2 standard revisited: Code flow

Matto Marjanovic maddog@mir.com
Mon, 9 Dec 2002 19:53:33 -0500

 >From: Oliver Rauch <oliver.rauch@rauch-domain.de>
 >Date: Mon, 9 Dec 2002 23:36:22 +0100
 >On Friday 06 December 2002 20:24, Henning Meier-Geinitz wrote:
 >> Proposal:
 >but this would make the sane_cancel unnecessaryly complex
 >because you have to call
 >	sane_cancel
 >	while (sane_read != SANE_STATUS_EOF);
 >and wait until sane_read really reutrnes SANE_STATUS_EOF.
 >I suggest to keep this like it is: no need to call sane_read when
 >sane_cancel is called!

I don't like the semantics of sane_cancel(), because they are overloaded
 and unclear.

The problem is that a backend may have resources that need to be cleaned
 up at the end of a scan.  sane_cancel() should not be used to both
 (a) asynchronously signal a cancel request, and (b) clean up the resources.
 Why?  Because those resources may be in use if during an asynchonous call.

 (I.e. sane_canel() can't free a buffer being used by sane_read() while
  in the middle of sane_read()!)

To make such a set-up work requires a lot of real careful coding, and flags,
 and it probably introduces race conditions that are unavoidable.

I propose that sane_cancel() be used *only* to request the end of a scan,
 and any/all cleanup should be done in sane_start() or sane_read().

Here is my proposal:

0) Prerequisites:

     Remove the get_select_fd() stuff.
     Remove the multi-frame stuff.
     Change sane_start() so that it also returns to true image parameters:

          SANE_Status sane_start(SANE_Handle h, SANE_Parameters *p);
     [since sane_get_parameters() is *always* called after sane_start().
      Allowing sane_start() to simply return the true parameters itself
      prevents some confusion involving sane_cancel() later on...]

1) Semantics of Image Acquisition Cycle ["IAC"]:

   a) An IAC begins when sane_start() is called.

   b) During an IAC, the only device-dependent functions (those requiring
       a device handle) which may be called are:
         - sane_read()
         - sane_cancel()

   c) An IAC ends when sane_read() or sane_start() returns unsuccessfully
       (status != SANE_STATUS_GOOD).
      At the end of the cycle (during that last call to sane_read() or
       sane_start()), the backend is allowed to free any resources which
       it allocated for the cycle.

   d) An IAC ends *successfully* if it ends due to sane_read() returning
       (status == SANE_STATUS_EOF).
      Otherwise, the IAC has ended in *failure*.

2) Semantics of sane_cancel():

   a) sane_cancel() may be called, asynchronously or synchronously, to tell
       the backend to abort the current IAC.
      If no IAC is in progress, sane_cancel() has no effect.

   b) If sane_cancel() is called synchronously, the next call to sane_read()
       is guaranteed to return (status != SANE_STATUS_GOOD) and the IAC is
       guaranteed to end.
      (The IAC may still end successfully, however.)

   c) If sane_cancel() is called asynchronously, during the exection of
       sane_start() or sane_read(), then that function should unblock and
       return as quickly as possible.
      However, following (1c) above, unless that sane_start() or sane_read()
       returns (status != SANE_STATUS_GOOD), the image acquisition cycle is
       not yet finished.
      [This is because the function may be in the midst of returning 
       SANE_STATUS_GOOD when sane_cancel() is called!]
                           Thus, one last call to sane_read() may be required.

-matt "semantics, semantics, semantics!" m.