libamxb  4.8.2
Bus Agnostic C API
Remote Function Invoke

Data Structures

struct  _amxb_request
 A request structure. More...
 

Functions

int amxb_new_invoke (amxb_invoke_t **invoke_ctx, amxb_bus_ctx_t *const ctx, const char *object, const char *interface, const char *method)
 Prepares a remote function invocation. More...
 
void amxb_free_invoke (amxb_invoke_t **invoke_ctx)
 Deletes a function invoke context, and frees allocated memory. More...
 
int amxb_invoke (amxb_invoke_t *invoke_ctx, amxc_var_t *args, amxc_var_t *ret, amxb_be_cb_fn_t fn, void *priv, int timeout)
 Invokes a remote function, as defined by the function invoke context. More...
 
int amxb_async_invoke (amxb_invoke_t *invoke_ctx, amxc_var_t *args, amxb_be_cb_fn_t fn, amxb_be_done_cb_fn_t done_fn, void *priv, amxb_request_t **req)
 Invokes a remote function, as defined by the function invoke context. More...
 
int amxb_wait_for_request (amxb_request_t *req, int timeout)
 Waits for an asynchronous remote function invoke to finish. More...
 
int amxb_request_new (amxb_request_t **request)
 Allocates an empty amxb_request_t. More...
 
amxb_bus_ctx_tamxb_request_get_ctx (amxb_request_t *request)
 Get the bus context of the request if any. More...
 
int amxb_close_request (amxb_request_t **req)
 Closes a previously create remote function called context. More...
 

Detailed Description

Function Documentation

◆ amxb_async_invoke()

int amxb_async_invoke ( amxb_invoke_t invoke_ctx,
amxc_var_t *  args,
amxb_be_cb_fn_t  fn,
amxb_be_done_cb_fn_t  done_fn,
void *  priv,
amxb_request_t **  req 
)

Invokes a remote function, as defined by the function invoke context.

Before invoking a function, an function invoke context must be created using amxb_new_invoke.

This method returns immediately, without waiting for the result (asynchronous I/O), to be able to receive the result of remote function call it is recommended that you use an eventloop.

The arguments passed must be in a amxc variant of type AMXC_VAR_ID_HTABLE. The order of the arguments is not important.

A callback function can be given, which is called for each individual return value. The private data will be passed to the callback function. If no callback function is given, the return values can be fetched from the request context, see _amxb_request

A done callback function can be given, which is called when the remote function call is finished. The private data will be passed to the done callback function. It is recommended to provide a done function, unless you are not interested when the remote function is done.

Note
This function allocates memory to store the request information. When the request is not needed anymore it must be freed using amxb_close_request.
Warning
When the connection represented by the bus context (amxb_bus_ctx) is closed, the allocated request is removed and can not be used anymore.
Parameters
invoke_ctxThe function invoke context as created with amxb_new_invoke
argsthe function arguments in a amxc variant htable type
fna callback function
done_fna done callback function
privprivate data that will be passed to the callback function (optional, can be NULL)
reqthe request context.
Returns

Definition at line 396 of file amxb_ba_invoke.c.

401  {
402  int retval = -1;
403  amxb_bus_ctx_t* ctx = NULL;
404  amxb_req_t* req = NULL;
405 
406  when_null(invoke_ctx, exit);
407  when_null(invoke_ctx->it.llist, exit);
408  when_null(request, exit);
409  ctx = amxc_container_of(invoke_ctx->it.llist, amxb_bus_ctx_t, invoke_ctxs);
410 
411  req = (amxb_req_t*) calloc(1, sizeof(amxb_req_t));
412  when_null(req, exit);
413  *request = &req->data;
414 
415  amxc_var_new(&req->data.result);
416  req->data.cb_fn = fn;
417  req->data.done_fn = done_fn;
418  req->data.priv = priv;
419 
420  if(amxb_is_local_object(ctx, invoke_ctx->object)) {
421  req->local = true;
422  retval = amxb_invoke_local_impl(invoke_ctx, ctx, args, *request, true);
423  } else {
424  req->local = false;
425  retval = amxb_invoke_be_impl(invoke_ctx, ctx, args, *request, 0, true);
426  }
427 
428  if(retval == 0) {
429  amxc_llist_append(&ctx->requests, &req->it);
430  }
431 
432 exit:
433  if((retval != 0) && (req != NULL)) {
434  amxc_var_delete(&req->data.result);
435  free(req);
436  *request = NULL;
437  }
438 
439  return retval;
440 }
static int amxb_invoke_local_impl(amxb_invoke_t *invoke_ctx, amxb_bus_ctx_t *ctx, amxc_var_t *args, amxb_request_t *request, bool async)
static int amxb_invoke_be_impl(amxb_invoke_t *invoke_ctx, amxb_bus_ctx_t *ctx, amxc_var_t *args, amxb_request_t *request, int timeout, bool async)
bool PRIVATE amxb_is_local_object(amxb_bus_ctx_t *ctx, const char *obj_path)
Definition: amxb_ba_priv.c:94
amxc_llist_t requests
Definition: amxb_types.h:118
amxc_llist_it_t it
Definition: amxb_types.h:150
char * object
Definition: amxb_types.h:151
amxc_var_t * result
Definition: amxb_types.h:140
amxb_be_cb_fn_t cb_fn
Definition: amxb_types.h:141
amxb_be_done_cb_fn_t done_fn
Definition: amxb_types.h:142
Definition: amxb_priv.h:69
amxc_llist_it_t it
Definition: amxb_priv.h:70
amxb_request_t data
Definition: amxb_priv.h:71
bool local
Definition: amxb_priv.h:72

◆ amxb_close_request()

int amxb_close_request ( amxb_request_t **  req)

Closes a previously create remote function called context.

Deletes and frees the request context created with amxb_async_invoke.

When the context is deleted, none of the callback functions will be called, not event when the remote function call was not yet finished.

Parameters
reqThe remote function invoke request
Returns

Definition at line 498 of file amxb_ba_invoke.c.

498  {
499  int retval = -1;
500  const amxb_bus_ctx_t* ctx = NULL;
501  const amxb_be_funcs_t* fns = NULL;
502  amxb_req_t* req = NULL;
503 
504  when_null(request, exit);
505  when_null((*request), exit);
506 
507  req = amxc_container_of(*request, amxb_req_t, data);
508  amxc_var_delete(&(*request)->result);
509 
510  if(req->in_flight || req->wait) {
511  req->closed = true;
512  *request = NULL;
513  retval = 0;
514  goto exit;
515  }
516 
517  retval = 0;
518  when_false(amxc_llist_it_is_in_list(&req->it), exit_free);
519 
520  ctx = amxc_container_of(req->it.llist, amxb_bus_ctx_t, requests);
521  fns = ctx->bus_fn;
522 
523  if(amxb_is_valid_be_func(fns, close_request, fns->close_request)) {
524  retval = fns->close_request(ctx->bus_ctx, *request);
525  } else {
527  }
528 
529  amxc_llist_it_take(&req->it);
530 
531 exit_free:
532  free(req);
533  *request = NULL;
534 exit:
535  return retval;
536 }
#define amxb_is_valid_be_func(ft, member, ptr)
Definition: amxb_priv.h:78
#define AMXB_ERROR_NOT_SUPPORTED_OP
Function/operation not supported.
Definition: amxb_error.h:110
The back-end interface structure.
amxb_be_close_request_fn_t close_request
const amxb_be_funcs_t * bus_fn
Definition: amxb_types.h:121
void * bus_ctx
Definition: amxb_types.h:122
bool in_flight
Definition: amxb_priv.h:73
bool closed
Definition: amxb_priv.h:74
bool wait
Definition: amxb_priv.h:75

◆ amxb_free_invoke()

void amxb_free_invoke ( amxb_invoke_t **  invoke_ctx)

Deletes a function invoke context, and frees allocated memory.

Frees the allocated memory for the function invoke context.

Parameters
invoke_ctxThe function invoke context, is reset to NULL

Definition at line 324 of file amxb_ba_invoke.c.

324  {
325  const amxb_be_funcs_t* fns = NULL;
326  amxb_bus_ctx_t* ctx = NULL;
327 
328  when_null(invoke_ctx, exit);
329  when_null(*invoke_ctx, exit);
330 
331  if(amxc_llist_it_is_in_list(&(*invoke_ctx)->it)) {
332  ctx = amxc_container_of((*invoke_ctx)->it.llist,
333  amxb_bus_ctx_t, invoke_ctxs);
334  fns = ctx->bus_fn;
335  if(amxb_is_valid_be_func(fns, free_invoke, fns->free_invoke)) {
336  fns->free_invoke(*invoke_ctx);
337  }
338  }
339 
340  amxc_llist_it_take(&(*invoke_ctx)->it);
341  free((*invoke_ctx)->object);
342  free((*invoke_ctx)->interface);
343  free((*invoke_ctx)->method);
344  free((*invoke_ctx));
345 
346  *invoke_ctx = NULL;
347 
348 exit:
349  return;
350 }
amxb_be_free_invoke_fn_t free_invoke

◆ amxb_invoke()

int amxb_invoke ( amxb_invoke_t invoke_ctx,
amxc_var_t *  args,
amxc_var_t *  ret,
amxb_be_cb_fn_t  fn,
void *  priv,
int  timeout 
)

Invokes a remote function, as defined by the function invoke context.

Before invoking a function, an function invoke context must be created using amxb_new_invoke.

This method is blocking, it will return when the remote function call is done or when it has failed.

The arguments passed must be in a amxc variant of type AMXC_VAR_ID_HTABLE. The order of the arguments is not important.

The return value must be an initialized amxc variant, the type must not be set.

Optionally a callback function can be given, which is called for each individual return value. The private data will be passed to the callback function.

As this function is blocking, a time out in seconds, must be provided. If the remote function call is not done in the given timeout, the function call (on the client side) is aborted.

Parameters
invoke_ctxThe function invoke context as created with amxb_new_invoke
argsthe function arguments in a amxc variant htable type
retwhen the remote function call is done, it will contain an array of return values.
fna callback function (optional, can be NULL).
privprivate data that will be passed to the callback function (optional, can be NULL)
timeoutin seconds
Returns

Definition at line 352 of file amxb_ba_invoke.c.

357  {
358  int retval = -1;
359  amxb_bus_ctx_t* ctx = NULL;
360  amxc_var_t temp_var;
361  amxb_req_t* req = NULL;
362  amxb_request_t* request = NULL;
363 
364  amxc_var_init(&temp_var);
365 
366  when_null(invoke_ctx, exit);
367  when_null(invoke_ctx->it.llist, exit);
368 
369  ctx = amxc_container_of(invoke_ctx->it.llist, amxb_bus_ctx_t, invoke_ctxs);
370  req = (amxb_req_t*) calloc(1, sizeof(amxb_req_t));
371  when_null(req, exit);
372  request = &req->data;
373 
374  request->result = (ret == NULL) ? &temp_var : ret;
375  request->cb_fn = fn;
376  request->done_fn = NULL;
377  request->bus_retval = 0;
378  request->bus_data = NULL;
379  request->priv = priv;
380 
381  if(amxb_is_local_object(ctx, invoke_ctx->object)) {
382  retval = amxb_invoke_local_impl(invoke_ctx, ctx, args, request, false);
383  if(retval == amxd_status_deferred) {
384  retval = amxb_invoke_wait_local(req, timeout);
385  }
386  } else {
387  retval = amxb_invoke_be_impl(invoke_ctx, ctx, args, request, timeout, false);
388  }
389  free(req);
390 
391 exit:
392  amxc_var_clean(&temp_var);
393  return retval;
394 }
static int amxb_invoke_wait_local(amxb_req_t *req, int timeout)
A request structure.
Definition: amxb_types.h:138
void * bus_data
Definition: amxb_types.h:144

◆ amxb_new_invoke()

int amxb_new_invoke ( amxb_invoke_t **  invoke_ctx,
amxb_bus_ctx_t *const  ctx,
const char *  object,
const char *  interface,
const char *  method 
)

Prepares a remote function invocation.

Allocates a remote function invoke context. Depending on the bus specific backend used, this function prepares the remote function invoke.

The created function invoke context can be re-used many times to call the same function.

Note
This function allocates memory for the function invoke context. The context can be freed using amxb_free_invoke
Warning
When the connection represented by the bus context (amxb_bus_ctx) is closed, the allocated invoke_ctx is removed and can not be used anymore.
Parameters
invoke_ctxThe place where the function invoke context is stored
ctxthe bus connection context
objectthe path to the object (mandatory)
interfacethe interface name, that contains the function (optional) when not used provide a NULL pointer
methodthe name of the function that is going to be called (mandatory)
Returns

Definition at line 281 of file amxb_ba_invoke.c.

285  {
286  int retval = amxd_status_unknown_error;
287  const amxb_be_funcs_t* fns = NULL;
288 
289  when_null(invoke_ctx, exit);
290  when_not_null(*invoke_ctx, exit);
291  when_null(ctx, exit);
292  when_null(ctx->bus_ctx, exit);
293  when_str_empty(method, exit);
294 
295  *invoke_ctx = (amxb_invoke_t*) calloc(1, sizeof(amxb_invoke_t));
296  when_null((*invoke_ctx), exit);
297 
298  (*invoke_ctx)->object = object == NULL ? strdup("") : strdup(object);
299  when_null((*invoke_ctx)->object, exit);
300  (*invoke_ctx)->interface = interface == NULL ? NULL : strdup(interface);
301  (*invoke_ctx)->method = strdup(method);
302  when_null((*invoke_ctx)->method, exit);
303 
304  amxb_trim((*invoke_ctx)->object, isdot);
305  amxb_trim((*invoke_ctx)->method, isbrace);
306 
307  fns = ctx->bus_fn;
308  if(amxb_is_valid_be_func(fns, new_invoke, fns->new_invoke)) {
309  retval = fns->new_invoke(*invoke_ctx);
310  } else {
311  retval = 0;
312  }
313 
314  if(retval == 0) {
315  amxc_llist_append(&ctx->invoke_ctxs, &(*invoke_ctx)->it);
316  } else {
317  amxb_free_invoke(invoke_ctx);
318  }
319 
320 exit:
321  return retval;
322 }
static void amxb_trim(char *str, amxc_string_is_char_fn_t fn)
static int isdot(int c)
static int isbrace(int c)
void amxb_free_invoke(amxb_invoke_t **invoke_ctx)
Deletes a function invoke context, and frees allocated memory.
amxb_be_new_invoke_fn_t new_invoke
amxc_llist_t invoke_ctxs
Definition: amxb_types.h:119

◆ amxb_request_get_ctx()

amxb_bus_ctx_t* amxb_request_get_ctx ( amxb_request_t request)

Get the bus context of the request if any.

Returns the bus context for which the request was created.

Parameters
requestthe request pointer
Returns
returns the bus context, NULL if the request is not associated with a bus context.

Definition at line 484 of file amxb_ba_invoke.c.

484  {
485  amxb_req_t* req = NULL;
486  amxb_bus_ctx_t* ctx = NULL;
487 
488  when_null(request, exit);
489  req = amxc_container_of(request, amxb_req_t, data);
490  if(amxc_llist_it_is_in_list(&req->it)) {
491  ctx = amxc_container_of(req->it.llist, amxb_bus_ctx_t, requests);
492  }
493 
494 exit:
495  return ctx;
496 }

◆ amxb_request_new()

int amxb_request_new ( amxb_request_t **  request)

Allocates an empty amxb_request_t.

Allocates and initializes an empty amxb_request_t.

This function is mainly intended for use in back-end implementations. Client applications should use amxb_async_invoke to allocate and initialize such a structure.

Parameters
requestthe request pointer to initialize
Returns

Definition at line 470 of file amxb_ba_invoke.c.

470  {
471  amxb_req_t* req = NULL;
472  int retval = AMXB_ERROR_UNKNOWN;
473 
474  req = (amxb_req_t*) calloc(1, sizeof(amxb_req_t));
475  when_null(req, exit);
476 
477  *request = &req->data;
478  retval = AMXB_STATUS_OK;
479 
480 exit:
481  return retval;
482 }
#define AMXB_ERROR_UNKNOWN
Unknown error.
Definition: amxb_error.h:80
#define AMXB_STATUS_OK
All ok.
Definition: amxb_error.h:86

◆ amxb_wait_for_request()

int amxb_wait_for_request ( amxb_request_t req,
int  timeout 
)

Waits for an asynchronous remote function invoke to finish.

Waits until a remote function invoke, created with amxb_async_invoke is finished.

When a done callback was provided, the done callback will be called before this function returns, unless a timeout occurs.

Parameters
reqThe remote function invoke request
timeoutin seconds
Returns

Definition at line 442 of file amxb_ba_invoke.c.

442  {
443  int retval = -1;
444  amxb_req_t* req = NULL;
445  const amxb_be_funcs_t* fns = NULL;
446  const amxb_bus_ctx_t* ctx = NULL;
447 
448  when_null(request, exit);
449  req = amxc_container_of(request, amxb_req_t, data);
450 
451  if(req->local) {
452  retval = amxb_invoke_wait_local(req, timeout);
453  goto exit;
454  }
455 
456  ctx = amxb_request_get_ctx(request);
457  when_null(ctx, exit);
458  fns = ctx->bus_fn;
459 
460  if(amxb_is_valid_be_func(fns, wait_request, fns->wait_request)) {
461  retval = fns->wait_request(ctx->bus_ctx, request, timeout);
462  } else {
464  }
465 
466 exit:
467  return retval;
468 }
amxb_bus_ctx_t * amxb_request_get_ctx(amxb_request_t *request)
Get the bus context of the request if any.
amxb_be_wait_request_fn_t wait_request