## VipsThreadState

VipsThreadState — pools of worker threads

## Stability Level

Stable, unless otherwise indicated

## Synopsis

    #include <vips/vips.h>

                        VipsThreadState;
                        VipsThreadStateClass;
    void *              vips_thread_state_set               (VipsObject *object,
                                                             void *a,
                                                             void *b);
    VipsThreadState *   vips_thread_state_new               (VipsImage *im,
                                                             void *a);
    VipsThreadState *   (*VipsThreadStart)                  (VipsImage *im,
                                                             void *a);
    int                 (*VipsThreadpoolAllocate)           (VipsThreadState *state,
                                                             void *a,
                                                             gboolean *stop);
    int                 (*VipsThreadpoolWork)               (VipsThreadState *state,
                                                             void *a);
    int                 (*VipsThreadpoolProgress)           (void *a);
    int                 vips_threadpool_run                 (VipsImage *im,
                                                             VipsThreadStart start,
                                                             VipsThreadpoolAllocate allocate,
                                                             VipsThreadpoolWork work,
                                                             VipsThreadpoolProgress progress,
                                                             void *a);
    void                vips_get_tile_size                  (VipsImage *im,
                                                             int *tile_width,
                                                             int *tile_height,
                                                             int *nlines);
    int                 (*VipsRegionWrite)                  (VipsRegion *region,
                                                             VipsRect *area,
                                                             void *a);
    int                 vips_sink_disc                      (VipsImage *im,
                                                             VipsRegionWrite write_fn,
                                                             void *a);
    void *              (*VipsStart)                        (VipsImage *out,
                                                             void *a,
                                                             void *b);
    int                 (*VipsGenerate)                     (VipsRegion *out,
                                                             void *seq,
                                                             void *a,
                                                             void *b);
    int                 (*VipsStop)                         (void *seq,
                                                             void *a,
                                                             void *b);
    int                 vips_sink                           (VipsImage *im,
                                                             VipsStart start,
                                                             VipsGenerate generate,
                                                             VipsStop stop,
                                                             void *a,
                                                             void *b);
    int                 vips_sink_tile                      (VipsImage *im,
                                                             int tile_width,
                                                             int tile_height,
                                                             VipsStart start,
                                                             VipsGenerate generate,
                                                             VipsStop stop,
                                                             void *a,
                                                             void *b);
    void                (*VipsSinkNotify)                   (VipsImage *im,
                                                             VipsRect *rect,
                                                             void *a);
    int                 vips_sink_screen                    (VipsImage *in,
                                                             VipsImage *out,
                                                             VipsImage *mask,
                                                             int tile_width,
                                                             int tile_height,
                                                             int max_tiles,
                                                             int priority,
                                                             VipsSinkNotify notify,
                                                             void *a);
    int                 vips_image_cache                    (VipsImage *in,
                                                             VipsImage *out,
                                                             int width,
                                                             int height,
                                                             int max);
    int                 vips_sink_memory                    (VipsImage *im);
    void                vips__print_renders                 (void);
    void                vips_concurrency_set                (int concurrency);
    int                 vips_concurrency_get                (void);

## Object Hierarchy

      GObject
       +----VipsObject
             +----VipsThreadState

## Description

`vips_threadpool_run()` loops a set of threads over an image. Threads take it in turns to allocate units of work (a unit might be a tile in an image), then run in parallel to process those units. An optional progress function can be used to give feedback.

## Details

### VipsThreadState

    typedef struct {
    	/* Image we run on.
    	 */
    	VipsImage *im;

    	/* This region is created and destroyed by the threadpool for the
    	 * use of the worker.
    	 */
    	VipsRegion *reg;

    	/* Neither used nor set, do what you like with them.
    	 */
    	VipsRect pos;
    	int x, y;

    	/* The client data passed to the enclosing vips_threadpool_run().
    	 */
            void *a;
    } VipsThreadState;

These per-thread values are carried around for your use by `vips_threadpool_run()`. They are private to each thread, so they are a useful place for VipsThreadpoolAllocate and VipsThreadpoolWork to communicate.

`reg` is created for you at the start of processing and freed at the end, but you can do what you like with it.

VipsImage *`im`; | the VipsImage being operated upon
VipsRegion *`reg`; | a REGION
VipsRect `pos`; | a Rect
int `x`; | an int
int `y`; | an int
void *`a`; | client data

### VipsThreadStateClass

    typedef struct {
    	VipsObjectClass parent_class;
    } VipsThreadStateClass;

### vips_thread_state_set ()

    void *              vips_thread_state_set               (VipsObject *object,
                                                             void *a,
                                                             void *b);

### vips_thread_state_new ()

    VipsThreadState *   vips_thread_state_new               (VipsImage *im,
                                                             void *a);

### VipsThreadStart ()

    VipsThreadState *   (*VipsThreadStart)                  (VipsImage *im,
                                                             void *a);

### VipsThreadpoolAllocate ()

    int                 (*VipsThreadpoolAllocate)           (VipsThreadState *state,
                                                             void *a,
                                                             gboolean *stop);

### VipsThreadpoolWork ()

    int                 (*VipsThreadpoolWork)               (VipsThreadState *state,
                                                             void *a);

### VipsThreadpoolProgress ()

    int                 (*VipsThreadpoolProgress)           (void *a);

### vips_threadpool_run ()

    int                 vips_threadpool_run                 (VipsImage *im,
                                                             VipsThreadStart start,
                                                             VipsThreadpoolAllocate allocate,
                                                             VipsThreadpoolWork work,
                                                             VipsThreadpoolProgress progress,
                                                             void *a);

This function runs a set of threads over an image. Each thread first calls `start` to create new per-thread state, then runs `allocate` to set up a new work unit (perhaps the next tile in an image, for example), then `work` to process that work unit. After each unit is processed, `progress` is called, so that the operation can give progress feedback. `progress` may be `NULL`.

Each thread has private state that the `allocate` and `work` functions can use to communicate. This state is created by each worker as it starts using `start`. Use the state destructor to clean up.

`allocate` and `start` are always single-threaded (so they can write to the per-pool state), whereas `work` can be executed concurrently. `progress` is always called by the main thread (ie. the thread which called `vips_threadpool_run()`).

See also: `vips_concurrency_set()`.

`im` : | image to loop over
`start` : | allocate per-thread state
`allocate` : | allocate a work unit
`work` : | process a work unit
`progress` : | give progress feedback about a work unit, or `NULL`
`a` : | client data
Returns : | 0 on success, or -1 on error.

### vips_get_tile_size ()

    void                vips_get_tile_size                  (VipsImage *im,
                                                             int *tile_width,
                                                             int *tile_height,
                                                             int *nlines);

Pick a tile size and a buffer height for this image and the current value of `vips_concurrency_get()`. The buffer height will always be a multiple of tile_height.

`im` : | image to guess for
`tile_width` : | return selected tile width
`tile_height` : | return selected tile height
`nlines` : | return buffer height in scanlines

### VipsRegionWrite ()

    int                 (*VipsRegionWrite)                  (VipsRegion *region,
                                                             VipsRect *area,
                                                             void *a);

The function should write the pixels in `area` from `region`. `a` is the value passed into `vips_discsink()`.

See also: `vips_sink_disc()`.

`region` : | get pixels from here
`area` : | area to write
`a` : | client data
Returns : | 0 on success, -1 on error.

### vips_sink_disc ()

    int                 vips_sink_disc                      (VipsImage *im,
                                                             VipsRegionWrite write_fn,
                                                             void *a);

`vips_sink_disc()` loops over `im`, top-to-bottom, generating it in sections. As each section is produced, `write_fn` is called.

`write_fn` is always called single-threaded (though not always from the same thread), it's always given image sections in top-to-bottom order, and there are never any gaps.

This operation is handy for making image sinks which output to things like disc files.

See also: `vips_concurrency_set()`.

`im` : | image to process
`write_fn` : | called for every batch of pixels
`a` : | client data
Returns : | 0 on success, -1 on error.

### VipsStart ()

    void *              (*VipsStart)                        (VipsImage *out,
                                                             void *a,
                                                             void *b);

### VipsGenerate ()

    int                 (*VipsGenerate)                     (VipsRegion *out,
                                                             void *seq,
                                                             void *a,
                                                             void *b);

### VipsStop ()

    int                 (*VipsStop)                         (void *seq,
                                                             void *a,
                                                             void *b);

### vips_sink ()

    int                 vips_sink                           (VipsImage *im,
                                                             VipsStart start,
                                                             VipsGenerate generate,
                                                             VipsStop stop,
                                                             void *a,
                                                             void *b);

Loops over an image. `generate` is called for every pixel in the image, with the `reg` argument being a region of pixels for processing. `vips_sink()` is used to implement operations like `im_avg()` which have no image output.

Each set of pixels is sized according to the requirements of the image pipeline that generated `im`.

See also: `vips_image_generate()`, `vips_image_new()`.

`im` : | scan over this image
`start` : | start sequences with this function
`generate` : | generate pixels with this function
`stop` : | stop sequences with this function
`a` : | user data
`b` : | user data
Returns : | 0 on success, or -1 on error.

### vips_sink_tile ()

    int                 vips_sink_tile                      (VipsImage *im,
                                                             int tile_width,
                                                             int tile_height,
                                                             VipsStart start,
                                                             VipsGenerate generate,
                                                             VipsStop stop,
                                                             void *a,
                                                             void *b);

Loops over an image. `generate` is called for every pixel in the image, with the `reg` argument being a region of pixels for processing. `vips_sink_tile()` is used to implement operations like `im_avg()` which have no image output.

Each set of pixels is `tile_width` by `tile_height` pixels (less at the image edges). This is handy for things like writing a tiled TIFF image, where tiles have to be generated with a certain size.

See also: `vips_sink()`, `vips_get_tile_size()`.

`im` : | scan over this image
`tile_width` : | tile width
`tile_height` : | tile height
`start` : | start sequences with this function
`generate` : | generate pixels with this function
`stop` : | stop sequences with this function
`a` : | user data
`b` : | user data
Returns : | 0 on success, or -1 on error.

### VipsSinkNotify ()

    void                (*VipsSinkNotify)                   (VipsImage *im,
                                                             VipsRect *rect,
                                                             void *a);

### vips_sink_screen ()

    int                 vips_sink_screen                    (VipsImage *in,
                                                             VipsImage *out,
                                                             VipsImage *mask,
                                                             int tile_width,
                                                             int tile_height,
                                                             int max_tiles,
                                                             int priority,
                                                             VipsSinkNotify notify,
                                                             void *a);

This operation renders `in` in the background, making pixels available on `out` as they are calculated. The `notify` callback is run every time a new set of pixels are available. Calculated pixels are kept in a cache with tiles sized `tile_width` by `tile_height` pixels and with at most `max_tiles` tiles. If `max_tiles` is -1, the cache is of unlimited size (up to the maximum image size). The `mask` image is a one-band uchar image and has 255 for pixels which are currently in cache and 0 for uncalculated pixels.

Only a single sink is calculated at any one time, though many may be alive. Use `priority` to indicate which renders are more important: zero means normal priority, negative numbers are low priority, positive numbers high priority.

Calls to `vips_region_prepare()` on `out` return immediately and hold whatever is currently in cache for that VipsRect (check `mask` to see which parts of the VipsRect are valid). Any pixels in the VipsRect which are not in cache are added to a queue, and the `notify` callback will trigger when those pixels are ready.

The `notify` callback is run from one of the background threads. In the callback you need to somehow send a message to the main thread that the pixels are ready. In a glib-based application, this is easily done with `g_idle_add()`.

If `notify` is `NULL` then `vips_sink_screen()` runs synchronously. `vips_region_prepare()` on `out` will always block until the pixels have been calculated.

See also: `vips_image_cache()`, `im_tile_cache()`, `vips_region_prepare()`, `vips_sink_disc()`, `vips_sink()`.

`in` : | input image
`out` : | output image
`mask` : | mask image indicating valid pixels
`tile_width` : | tile width
`tile_height` : | tile height
`max_tiles` : | maximum tiles to cache
`priority` : | rendering priority
`notify` : | pixels are ready notification callback
`a` : | client data for callback
Returns : | 0 on sucess, -1 on error.

### vips_image_cache ()

    int                 vips_image_cache                    (VipsImage *in,
                                                             VipsImage *out,
                                                             int width,
                                                             int height,
                                                             int max);

### vips_sink_memory ()

    int                 vips_sink_memory                    (VipsImage *im);

Loops over an image, generating it to a memory buffer attached to the image.

See also: `vips_sink()`, `vips_get_tile_size()`.

`im` : | generate this image to memory
Returns : | 0 on success, or -1 on error.

### vips__print_renders ()

    void                vips__print_renders                 (void);

### vips_concurrency_set ()

    void                vips_concurrency_set                (int concurrency);

### vips_concurrency_get ()

    int                 vips_concurrency_get                (void);

## See Also

generate