xuzhenbao opened a new issue, #775:
URL: https://github.com/apache/celix/issues/775

   In some service usage scenarios, the result may not be returned immediately 
after the service call is completed, it may be returned through a callback 
function at some time after the service call is completed. How should we use 
callback functions in celix services (it includes remote services and local 
services)?
   
   In my opinion, it is unsafe to design function pointers directly in the 
service method parameters, because the service provider may have been destroyed 
after the service call is completed. At this time, if the callback function is 
called again, problems will occur. In addition, designing callback function 
pointers in the service method may make the implementation of RSA complex.
   
   Therefore, I think the callback function can be designed as a celix service. 
If a service method needs a callback function, the service method's input 
parameters should include the service identifier of the callback function 
(Maybe the service identifier is a string composed of `framework uuid` and 
`service id`). When calling the service method, the service caller needs to 
register the callback function service first, and then pass the callback 
function service identifier to the service method. The service provider can 
invoke the callback function through the callback function service. The example 
is as follows:
   ```c
   //provider api
   
   #define MY_SERVICE_NAME "my_service"
   #define MY_SERVICE_VERSION "1.0.0"
   
   typedef struct my_service {
       void* handle;
       void (*doSomething)(void *handle, const char *input, const char 
*callbackServiceUUID);
   } my_service_t;
   
   #define MY_SERVICE_CALLBACK_SERVICE_NAME "my_service_callback"
   #define MY_SERVICE_CALLBACK_SERVICE_VERSION "1.0.0"
   typedef struct callback_service {
       void* handle;
       void (*callback)(void *handle, const char *result);
   } callback_service_t;
   
   ```
   
   ```c
   //provider impl
   typedef struct provider {
       celix_bundle_context_t *context;
       my_service_t service;
       long svcId;
       long trkId;
   } provider_t;
   
   typedef struct use_callback_data {
       provider_t *provider;
       const char *input;
       const char *callbackServiceUUID;
   }use_callback_data_t;
   
   void useCallback(void *handle, void *svc) {
       use_callback_data_t *data = handle;
       callback_service_t *callback = svc;
       callback->callback(callback->handle, "result");
   }
   
   void my_service_doSomething(void *handle, const char *input, const char 
*callbackServiceUUID) {
       provider_t *provider = handle;
   
   // invoke callback service
       use_callback_data_t data = {provider, input, callbackServiceUUID};
       celix_bundleContext_useTrackedServices(provider->context, 
provider->trkId, &data, useCallback);
   }
   
   void provider_init(celix_bundle_context_t *context, provider_t *provider) {
       provider->context = context;
       provider->service.handle = provider;
       provider->service.doSomething = my_service_doSomething;
       provider->svcId = celix_bundleContext_registerService(context, 
&provider->service, MY_SERVICE_NAME, MY_SERVICE_VERSION, NULL);
   
   //track callback service
       celix_service_tracking_options_t opts = 
CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
       opts.filter.serviceName = MY_SERVICE_CALLBACK_SERVICE_NAME;
       provider->trkId = celix_bundleContext_trackServicesWithOptions(ctx, 
&opts);
   }
   ```
   
   ```c
   //consumer impl
   
   typedef struct consumer {
       celix_bundle_context_t *context;
       callback_service_t service;
       long svcId;
       long trkId;
   } consumer_t;
   
   void my_service_callback(void *handle, const char *result) {
       printf("my_service_callback called with result %s\n", result);
   }
   
   void useService(void *handle, void *svc) {
       consumer_t *consumer = handle;
       my_service_t *service = svc;
       service->doSomething(service->handle, "input", "<frameworkUUID>+<service 
id>");
   }
   
   void consumer_init(celix_bundle_context_t *context, consumer_t *consumer) {
   // register callback function service
       consumer->context = context;
       consumer->service.handle = consumer;
       consumer->service.callback = my_service_callback;
       consumer->svcId = celix_bundleContext_registerService(context, 
&consumer->service, MY_SERVICE_CALLBACK_SERVICE_NAME, 
MY_SERVICE_CALLBACK_SERVICE_VERSION, NULL);
   
   //use target service
       celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS;
       opts.filter.serviceName = MY_SERVICE_NAME;
       celix_bundleContext_useServiceWithOptions(context, &opts, consumer, 
useService);
   }
   ```
   @pnoltes 
   Do you have any suggestions for the design of callback function?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@celix.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to