Fct_Dispatch_...

 

Fct_Dispatch_TAG

Fct_Dispatch_GLI

Fct_Dispatch_Other

 

Muti-thread dispatch function.  For each frame in the"frame" list, this function will start the function "fct" in a separate thread.  It will limit the number of concurrent threads to "COMPUTER_THREAD_NB". The function "fct" will receive as argument a pointer to the "Struct_Dispatch_2" structure.

 

If the variable "increment" is set, Fct_Dispatch_... will use it to prevent the concurrent threads from working on adjacent frames.  For example, if "increment"=3, Dispatch will start threads with frames 0, 3, 6, 9, 12... instead of 0, 1, 2, 3, 4...  This is used if computation of the frame's gradient necessitate values from the target frames and its immediate neighbours. By spreading the computation with "increment=3" we insure that the threads are not blocking one another by working on the same frames.

 

The function will also replace the cursor by an hourglass while the threads are processing.

 

Once all threads are finished the function will update the appropriate structures ("UPDATE_DISPLAY_TAG" for Fct_Dispatch_TAG or "UPDATE_DISPLAY_GLI" for Fct_Dispatch_GLI) and generate a redraw ("REDRAW_DB_OPENGL" for Fct_Dispatch_TAG and Fct_Dispatch_GLI, "redraw_flag" from the Struct_Dispatch_1 structure for Fct_Dispatch_Other.).

 

The Fct_Dispatch_TAG will also attempt to keep all TAG pixel modifications in an Undo.  The label associated with the undo will be derived from the variables: "name" and "label" of the Struct_Dispatch_1 structure.

 

When the last user thread has finished, the function will place a "UPDATE_THREAD" signal in the update queue, and it will call the "fct_end" callback if it is present with a pointer to the "local_data" variable.

 

 

Syntax

 

unsigned __stdcall  Fct_Dispatch_TAG(

          void *pvoid

) ;

 

unsigned __stdcall  Fct_Dispatch_GLI(

          void *pvoid

) ;

 

unsigned __stdcall  Fct_Dispatch_Other(

          void *pvoid

) ;

 

Parameters

 

pvoid

Pointer to a Struct_Dispatch_1 structure.

 

typedef struct Struct_Dispatch_1 {

          char         *          name ;          // name for undo

          char         *          label ;          // label for undo

          UInt64          redraw_flag ;          // redraw flag for Dispatch_Other fct.

          int          nb_frame ;          // number of frames to process

          SliceO_Frame  **          frame ;          // list of the frames to process

          SliceO_Window  *          window ;          // pointer to current window

          int          increment ;          // spread of the dispatch to minimize neighbour interferences

          unsigned int          stack_size ;          // stack size if a special size is required (def=0)

          void         *          progress ;          // pointer to "Progress" window (def=0)

          void         *          fct_thread ;          // pointer to thread function ( unsigned int (*) (void *) )

          void         *          fct_end ;          // pointer to optional "end" callback function ( void (*) (void *) )

          void         *          local_data ;          // pointer to local data structure

} Struct_Dispatch_1 ;

 

 

Return value

 

This function returns "1".

 

 

Remarks

 

The function "fct". from the Struct_Dispatch_1 structure must call "Fct_Dispatch_End()" when it terminate.  Failure to do so will result in a deadlock.

 

The function "fct" from the struct_Dispatch_1 structure is called with a "_beginthreadex" call.

The argument "stack_size" is taken from the Struct_Dispatch_1 structure.

The function is provided with a pointer to a Struct_Dispatch_2 structure containing a pointer to the target frame.

 

typedef struct Struct_Dispatch_2 {

          SliceO_Frame  *          frame ;          // pointer to the frame to process

          SliceO_Window *          window ;          // pointer to current window

          void          *          progress ;          // pointer to "Progress" window (def=0)

          void          *          local_data ;          // pointer to local data structure

} Struct_Dispatch_2 ;

 

 

Requirements

 

Header:

          sliceO_include.hpp

 

 

Library:

          sliceO_Structures.lib

 

 

 

Example

 

...

 

int          Demo_Compute( void )

{

int          i=0 ;

void          *p_block = NULL ;

 

static          Struct_Dispatch_1 data ;

 

          memset( (void *) &data, NULL, sizeof(Struct_Dispatch_1) ) ;

 

          // --- I need a pointer to the current window ---

          data.window = (SliceO_Window *) Fct_Variable_Value( "$WINDOW_CUR" ) ;

          if ( ! data.window )

              return( 0 ) ;

 

          // --- how many images are selected/enabled ? ---

          unsigned int stack_size = 0 ;

          if ( Iterator_Init( ITERATOR_USER_1, "Demo_Compute" ) ) {

              while( SliceO_Frame *frame = (SliceO_Frame *) Iterator_Class( ITERATOR_USER_1, CLASS_ID_FRAME, data.window, ITER_FLAG_SELECT ) ) {

                    REALLOC( SliceO_Frame **, data.frame, data.nb_frame+1, sizeof(SliceO_Frame *) ) ;

                    data.frame[data.nb_frame++] = frame ;

              }

              Iterator_End( ITERATOR_USER_1 ) ;

          }

 

          // --- if no WS need to be computed, get out ---

          if ( ! data.nb_frame )

              return( 1 ) ;

 

          // --- we do not want this window to get under the others ---

          unsigned char *Interface_Lock_Focus = (unsigned char *) Fct_Variable_Get( "$INTERFACE_LOCK_FOCUS" ) ;

          if ( Interface_Lock_Focus )

              *Interface_Lock_Focus = 1 ;

 

          // --- open the progress report window (not if from a script!) ---

          if ( (data.nb_frame > 1) && ! (Script_Flag_Get() & SCRIPT_READ_LINE) )

              p_block = Progress_Init( hwnd, "Demo Progress", "Computing Demo" ) ;

          data.progress = p_block ;

 

          data.local_data = ... ;

          data.fct = Demo_Fct_Thread ;

 

          Error_Fct( hwnd, ERROR_CODE_REPORT, "Computing Watershed %d for \001%d\002 frames", merge+1, data.nb_frame ) ;

          Progress_Write( p_block, "Computing Watershed %d for \001%d\002 frames", merge+1, data.nb_frame ) ;

 

          Progress_Total( p_block, data.nb_frame ) ;

 

          HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0, Fct_Dispatch_TAG, &data, 0, NULL ) ;

          if ( hThread == 0 ) {

              int err_no = GetLastError() ;

              Error_Fct( hwnd, ERROR_CODE_ERROR, "Unable to start thread\n %s", Error_Windows(err_no) ) ;

              Error_Fct( hwnd, ERROR_CODE_TRACE, "file:%s line:%d", __FILE__, __LINE__ ) ;

 

              FREE( data.frame ) ;

              Progress_End( p_block ) ;

              if ( Interface_Lock_Focus )

                    *Interface_Lock_Focus = 0 ;

              return( NULL ) ;

          }

 

          CloseHandle( hThread ) ;

 

          return( 1 ) ;

}

 

// ----------------------------------------------------------------------------

//

//          Func:    Demo_Fct_Thread()

//

// ----------------------------------------------------------------------------

static          unsigned __stdcall Demo_Fct_Thread( void *pvoid )

{

SliceO_Window *window =     ((Struct_Dispatch_2 *) pvoid)->window ;

SliceO_Frame *frame =              ((Struct_Dispatch_2 *) pvoid)->frame ;

void              *progress =              ((Struct_Dispatch_2 *) pvoid)->progress ;

 

          if ( Progress_Abort( progress ) )

              goto abort ;

 

          // --- if image is locked: skip ---

          if ( frame->Lock_Get() ) {

                    Error_Fct( hwnd, ERROR_CODE_WARNING, "\xF1\005WARNING:\002 image locked!" ) ;

                    Error_Fct( hwnd, ERROR_CODE_WARNING, "\xF1\t skipping: \001%s", frame->Name_Get() ) ;

                    Progress_Write( progress, "\xF1\005WARNING:\xF0\002 image locked!" ) ;

                    Progress_Write( progress, "\002   skipping: \001%s", frame->Name_Get() ) ;

                    goto exit ;

          }

 

          // --- Place a lock on this frame ---

          frame->Lock_Set( 1 ) ;

 

          // --- highlight the frame we are working on ---

          frame->Flag_Set_On( CLASS_MODE_THIS, window, CLASS_FLAG_HIGHLIGHT_BLU ) ;

          Fct_Redraw( REDRAW_HIGHLIGHT, window, frame ) ;

 

          // ====================================================================

          // ==================== Local processing ==============================

          // ====================================================================

 

                    Progress_Inc( progress, 1 ) ;

 

                    // --- Feedback to the user ---

                    if ( strlen(frame->Name_Get()) <= 30 )

                              Progress_Write( progress, "Compute Demo for \001%s", merge+1, frame->Name_Get() ) ;

                    else

                              Progress_Write( progress, "Compute Demo for \001%8.8s...%19.19s", merge+1,

                                        frame->Name_Get(), frame->Name_Get() + strlen(frame->Name_Get()) - 19 ) ;

 

                    ...

 

          

          // ====================================================================

          // ==================== Cleanup and get out ===========================

          // ====================================================================

exit:

 

          // --- unlock the GLI image ---

          frame->Lock_Set( -1 ) ;

 

abort:

 

          // --- reset the highlight ----

          // Note: this is done outside the critical region, it could be dangerous...

          frame->Flag_Set_Off( CLASS_MODE_THIS, window, CLASS_FLAG_HIGHLIGHT_BLU ) ;

          Fct_Redraw( REDRAW_HIGHLIGHT, window, frame ) ;

 

          // --- signal that we have finished ---

          Fct_Dispatch_End() ;

 

          _endthreadex( 1 ) ;

          return( 1 ) ;

}

 

...

 

 

See also

 

Fct_Dispatch_End