## GdaWorker GdaWorker — Execute functions in a sub thread |

## Stability Level

Stable, unless otherwise indicated

## Functions

GdaWorker * | gda_worker_new ()
GdaWorker * | gda_worker_new_unique ()
GdaWorker * | gda_worker_ref ()
void | gda_worker_unref ()
gpointer | (*GdaWorkerFunc) ()
guint | gda_worker_submit_job ()
gboolean | gda_worker_fetch_job_result ()
gboolean | gda_worker_cancel_job ()
void | gda_worker_forget_job ()
gboolean | gda_worker_do_job ()
gpointer | gda_worker_wait_job ()
gboolean | gda_worker_thread_is_worker ()
void | (*GdaWorkerCallback) ()
gboolean | gda_worker_set_callback ()

## Types and Values

| GdaWorker

## Object Hierarchy

        GBoxed
        ╰── GdaWorker

## Includes

    #include <libgda/gda-statement-extra.h>

## Description

The purpose of the GdaWorker object is to execute "jobs" (functions with arguments) within a worker thread, using `gda_worker_submit_job()`.

Any code executing in any thread context can submit jobs to `worker` and is guaranted not to be blocked (except if using `gda_worker_wait_job()` or if the jobs are submitted within the worker thread itself). Once jobs have been submitted, it's up to the caller to regularly check if a job has completed using `gda_worker_fetch_job_result()`. If you don't want to have to check regularly (which is like some polling operation), then you can use `gda_worker_set_callback()` which adds a callback when any job has completed.

gda_worker_wait_job() allows you to execute a job in the worker thread while blocking the calling thread.

Before fetching a jobs's result, it is also possible to request the cancellation of the job using `gda_worker_cancel_job()`, or completely discard the job using `gda_worker_forget_job()`.

Jobs can also be submitted using `gda_worker_do_job()`, which internally runs a GMainLoop and allows you to execute a job while at the same time processing events for the specified GMainContext.

The GdaWorker implements its own locking mechanism and can safely be used from multiple threads at once without needing further locking.

## Functions

### gda_worker_new ()

    GdaWorker *
    gda_worker_new (void);

Creates a new GdaWorker object.

#### Returns

a new GdaWorker, or `NULL` if an error occurred.

[transfer full]

Since: 6.0

### gda_worker_new_unique ()

    GdaWorker *
    gda_worker_new_unique (GdaWorker **location,
                           gboolean allow_destroy);

This function creates a new GdaWorker, or reuses the one at `location` . Specifically:

1. if *`location` is `NULL`, then a new GdaWorker is created. In this case if `allow_destroy` is `FALSE`, then the returned GdaWorker's reference count is 2, thus preventing it form ever being destroyed (unless `gda_worker_unref()` is called somewhere else)

2. if *`location` is not `NULL`, the the GdaWorker it points to is returned, its reference count increased by 1

When the returned GdaWorker's reference count reaches 0, then it is destroyed, and *`location` is set to `NULL`.

In any case, the returned value is the same as *`location` .

#### Parameters

location | a place to store and test for existence, not `NULL` |
allow_destroy | defines if the created `GdaWorker` (see case 1 below) will allow its reference to drop to 0 and be destroyed |

#### Returns

a GdaWorker.

[transfer full]

### gda_worker_ref ()

    GdaWorker *
    gda_worker_ref (GdaWorker *worker);

Increases `worker` 's reference count.

#### Parameters

worker | a GdaWorker |

#### Returns

`worker` .

[transfer full]

Since: 6.0

### gda_worker_unref ()

    void
    gda_worker_unref (GdaWorker *worker);

Decreases `worker` 's reference count. When reference count reaches `0`, then the object is destroyed, note that in this case this function only returns when the worker thread actually has terminated, which can take some time if it's busy.

If `worker` is `NULL`, then nothing happens.

#### Parameters

worker | a GdaWorker, or `NULL`. | [nullable]

Since: 6.0

### GdaWorkerFunc ()

    gpointer
    (*GdaWorkerFunc) (gpointer user_data,
                      GError **error);

Specifies the type of function to be passed to `gda_worker_submit_job()`, `gda_worker_do_job()` and `gda_worker_wait_job()`.

#### Parameters

user_data | pointer to the data (which is the argument passed to `gda_worker_submit_job()`) |
error | a place to store errors |

#### Returns

a pointer to some data which will be returned by `gda_worker_fetch_job_result()`

### gda_worker_submit_job ()

    guint
    gda_worker_submit_job (GdaWorker *worker,
                           GMainContext *callback_context,
                           GdaWorkerFunc func,
                           gpointer data,
                           GDestroyNotify data_destroy_func,
                           GDestroyNotify result_destroy_func,
                           GError **error);

Request that the worker thread call `func` with the `data` argument.

Notes:

- if `data_destroy_func` is not `NULL`, then it will be called to destroy `data` when the job is removed, which can occur within the context of the worker thread, or within the context of any thread using `worker`.

- if `result_destroy_func` is not `NULL`, then it will be called to destroy the result produced by `func`. Similarly to `data_destroy_func`, if it is not `NULL` (and if there is a non `NULL` result), then that function can be called in the context of any thread.

- the error here can only report failures while executing `gda_worker_submit_job()`, not any error which may occur while executing `func` from the worker thread.

- when this function returns, the job may already have been completed, so you should not assume that the job is in any specific state.

- passing `NULL` for `callback_context` is similar to passing the result of `g_main_context_ref_thread_default()`

#### Parameters

worker | a GdaWorker object |
callback_context | a GMainContext, or `NULL` (ignored if no setting has been defined with `gda_worker_set_callback()`). | [nullable]
func | the function to call from the worker thread |
data | the data to pass to `func` , or `NULL`. | [nullable]
data_destroy_func | a function to destroy `data` , or `NULL`. | [nullable]
result_destroy_func | a function to destroy the result, if any, of the execution of `func` , or `NULL`. | [nullable]
error | a place to store errors, or `NULL`. | [nullable]

#### Returns

a job ID, or `0` if an error occurred

Since: 6.0

### gda_worker_fetch_job_result ()

    gboolean
    gda_worker_fetch_job_result (GdaWorker *worker,
                                 guint job_id,
                                 gpointer *out_result,
                                 GError **error);

Fetch the value returned by execution the `job_id` job.

Warning: if an error occurred during the execution of the requested function within the worker thread, then it will show as `error` , while the return value of this function will be `TRUE`.

Note: if there is a result, it will be stored in `out_result` , and it's up to the caller to free the result, the GdaWorker object will not do it (ownership of the result is transfered to the caller).

#### Parameters

worker | a GdaWorker object |
job_id | the ID of the job, as returned by `gda_worker_submit_job()` |
out_result | a place to store the value returned by the execution of the requested function within the worker thread, or `NULL`. | [nullable]
error | a place to store errors, or `NULL`. | [nullable]

#### Returns

`TRUE` if the jobs has completed

Since: 6.0

### gda_worker_cancel_job ()

    gboolean
    gda_worker_cancel_job (GdaWorker *worker,
                           guint job_id,
                           GError **error);

Cancels a job which has not yet been processed. If the job cannot be found, is being processed or has already been processed, then this function returns `FALSE`.

This function can be called on already cancelled jobs, and simply returns `TRUE` in that case.

#### Parameters

worker | a GdaWorker object |
job_id | the ID of the job, as returned by `gda_worker_submit_job()` |
error | a place to store errors, or `NULL`. | [nullable]

#### Returns

`TRUE` if the job was cancelled

Since: 6.0

### gda_worker_forget_job ()

    void
    gda_worker_forget_job (GdaWorker *worker,
                           guint job_id);

Forget all about the job with ID `job_id` . As opposed to `gda_worker_cancel_job()`, this function can be used to tell `worker` that whatever happens to the specific job, you are not interrested anymore (i.e. that `worker` can do whatever is possible to simple discard everything related to that job).

#### Parameters

worker | a GdaWorker object |
job_id | the ID of the job, as returned by `gda_worker_submit_job()` |

Since: 6.0

### gda_worker_do_job ()

    gboolean
    gda_worker_do_job (GdaWorker *worker,
                       GMainContext *context,
                       gint timeout_ms,
                       gpointer *out_result,
                       guint *out_job_id,
                       GdaWorkerFunc func,
                       gpointer data,
                       GDestroyNotify data_destroy_func,
                       GDestroyNotify result_destroy_func,
                       GError **error);

Request that the worker thread call `func` with the `data` argument, much like `gda_worker_submit_job()`, but waits (starting a GMainLoop) for a maximum of `timeout_ms` miliseconds for `func` to be executed.

If this function is called from within `worker` 's worker thread, then this function simply calls `func` with `data` and does not use `context` .

The following cases are possible if this function is not called from within `worker` 's worker thread:

- the call to `func` took less than `timeout_ms` miliseconds: the return value is `TRUE` and `out_result` contains the result of the `func`'s execution, and `out_job_id` contains `NULL`. Note in this case that `error` may still contain an error code if `func`'s execution produced an error. Also note that in this case any setting defined by `gda_worker_set_callback()` is not applied (as the result is immediately returned)

- The call to `func` takes more then `timeout_ms` miliseconds: the return value is `TRUE` and `out_result` is `NULL` and `out_job_id` contains the ID of the job as if it had been submitted using `gda_worker_submit_job()`. If `out_job_id` is `NULL`, and if no setting has been defined using `gda_worker_set_callback()`, then the job will be discarded (as if `gda_worker_forget_job()` had been called).

- The call to `func` could not be done (some kind of plumbing error for instance): the returned value is `FALSE` and `out_result` and `out_job_id` are set to `NULL` (if they are not `NULL`)

Notes:

- `result_destroy_func` is needed in case `out_result` is `NULL` (to avoid memory leaks)

- passing `NULL` for `context` is similar to passing the result of `g_main_context_ref_thread_default()`

#### Parameters

worker | a GdaWorker object |
context | a GMainContext to execute a main loop in (while waiting), or `NULL`. | [nullable]
timeout_ms | the maximum number of milisecons to wait before returning, or `0` for unlimited wait |
out_result | a place to store the result, if any, of `func` 's execution, or `NULL`. | [nullable]
out_job_id | a place to store the ID of the job having been submitted, or `NULL`. | [nullable]
func | the function to call from the worker thread |
data | the data to pass to `func` , or `NULL`. | [nullable]
data_destroy_func | a function to destroy `data` , or `NULL`. | [nullable]
result_destroy_func | a function to destroy the result, if any, of `func` 's execution, or `NULL`. | [nullable]
error | a place to store errors, or `NULL`. | [nullable]

#### Returns

`TRUE` if no error occurred

Since: 6.0

### gda_worker_wait_job ()

    gpointer
    gda_worker_wait_job (GdaWorker *worker,
                         GdaWorkerFunc func,
                         gpointer data,
                         GDestroyNotify data_destroy_func,
                         GError **error);

Request that the worker thread call `func` with the `data` argument, much like `gda_worker_submit_job()`, but waits (blocks) until `func` has been executed.

Note: it's up to the caller to free the result, the GdaWorker object will not do it (ownership of the result is transfered to the caller).

#### Parameters

worker | a GdaWorker object |
func | the function to call from the worker thread |
data | the data to pass to `func` , or `NULL`. | [nullable]
data_destroy_func | a function to destroy `data` , or `NULL`. | [nullable]
error | a place to store errors, or `NULL`. | [nullable]

#### Returns

the result of `func` 's execution.

[transfer full]

Since: 6.0

### gda_worker_thread_is_worker ()

    gboolean
    gda_worker_thread_is_worker (GdaWorker *worker);

Tells if the thread from which this function is called is `worker` 's worker thread.

#### Parameters

worker | a GdaWorker |

#### Returns

`TRUE` if this function is called is `worker` 's worker thread

Since: 6.0

### GdaWorkerCallback ()

    void
    (*GdaWorkerCallback) (GdaWorker *worker,
                          guint job_id,
                          gpointer result_data,
                          GError *error,
                          gpointer user_data);

### gda_worker_set_callback ()

    gboolean
    gda_worker_set_callback (GdaWorker *worker,
                             GMainContext *context,
                             GdaWorkerCallback callback,
                             gpointer user_data,
                             GError **error);

Declare a callback function to be called when a job has been processed. If `callback` is `NULL`, then any previously effect of this function is removed. If the same function is called with a different `callback` value, then the previous one is simply replaced.

Since this function adds a new source of events to the specified GMainContext (or the default one if `context` is `NULL`),

Notes:

- before calling this function, `worker` internally gets rid of the job, so the `jib_id` passed to `callback` does not actually designate a known job ID, and so calling `gda_worker_fetch_job_result()` for that job ID will fail

- the job's result, if any, has to be freed by `callback` (`worker` does not do it)

- any call to this function will only be honored for the jobs submitted _after_ calling it, the ones submitted before are not affected

- passing `NULL` for `context` is similar to passing the result of `g_main_context_ref_thread_default()`

#### Parameters

worker | a GdaWorker object |
context | a GMainContext, or `NULL`. | [nullable]
callback | the function to call when a job submitted from within the calling thread using `gda_worker_submit_job()` has finished being processed. | [nullable][scope call]
user_data | argument passed to `callback` |
error | a place to store errors, or `NULL`. | [nullable]

#### Returns

`TRUE` if no error occurred.

Since: 6.0

## Types and Values

### GdaWorker

    typedef struct _GdaWorker GdaWorker;