PengZheng commented on a change in pull request #399:
URL: https://github.com/apache/celix/pull/399#discussion_r816607673
##########
File path: libs/framework/src/bundle_context.c
##########
@@ -1181,78 +1182,70 @@ static void
celix_bundleContext_useServiceWithOptions_2_UseServiceTracker(void *
celix_bundle_context_use_service_data_t* d = data;
assert(celix_framework_isCurrentThreadTheEventLoop(d->ctx->framework));
- d->called = celix_serviceTracker_useHighestRankingService(d->svcTracker,
d->opts->filter.serviceName, d->opts->callbackHandle, d->opts->use,
d->opts->useWithProperties, d->opts->useWithOwner);
-}
-
-static void
celix_bundleContext_useServiceWithOptions_3_CloseServiceTracker(void *data) {
- celix_bundle_context_use_service_data_t* d = data;
- assert(celix_framework_isCurrentThreadTheEventLoop(d->ctx->framework));
-
- celix_service_tracker_t *tracker = d->svcTracker;
- d->svcTracker = NULL;
-
- celix_serviceTracker_destroy(tracker);
+ d->called = celix_serviceTracker_useHighestRankingService(d->svcTracker,
d->opts->filter.serviceName, 0, d->opts->callbackHandle, d->opts->use,
d->opts->useWithProperties, d->opts->useWithOwner);
}
bool celix_bundleContext_useServiceWithOptions(
celix_bundle_context_t *ctx,
const celix_service_use_options_t *opts) {
- if (opts == NULL) {
+ if (opts == NULL || opts->filter.serviceName == NULL) {
return false;
}
celix_bundle_context_use_service_data_t data = {0};
data.ctx = ctx;
data.opts = opts;
+ bool called = false;
if (celix_framework_isCurrentThreadTheEventLoop(ctx->framework)) {
// Ignore timeout: blocking the event loop prevents any progress to be
made
celix_bundleContext_useServiceWithOptions_1_CreateServiceTracker(&data);
celix_bundleContext_useServiceWithOptions_2_UseServiceTracker(&data);
- celix_bundleContext_useServiceWithOptions_3_CloseServiceTracker(&data);
+ celix_serviceTracker_destroy(data.svcTracker);
return data.called;
}
long eventId = celix_framework_fireGenericEvent(ctx->framework, -1,
celix_bundle_getId(ctx->bundle), "create service tracker for
celix_bundleContext_useServiceWithOptions", &data,
celix_bundleContext_useServiceWithOptions_1_CreateServiceTracker, NULL, NULL);
celix_framework_waitForGenericEvent(ctx->framework, eventId);
- celix_framework_waitForEmptyEventQueue(ctx->framework); //ensure that a
useService wait if a listener hooks concept, which triggers an async service
registration
- struct timespec startTime = celix_gettime(CLOCK_MONOTONIC);
- bool useServiceIsDone = false;
- bool called = false;
- do {
- eventId = celix_framework_fireGenericEvent(ctx->framework, -1,
celix_bundle_getId(ctx->bundle), "use service tracker for
celix_bundleContext_useServiceWithOptions", &data,
celix_bundleContext_useServiceWithOptions_2_UseServiceTracker, NULL, NULL);
- celix_framework_waitForGenericEvent(ctx->framework, eventId);
+ if(opts->flags & CELIX_SERVICE_USE_DIRECT) {
+ celix_framework_waitUntilNoPendingRegistration(ctx->framework); //
TL;DR make "service on demand" pattern work. Try comment it out and run
CelixBundleContextServicesTests.UseServiceOnDemandDirectlyWithAsyncRegisterTest
Review comment:
Now `CELIX_SERVICE_USE_DIRECT` will not support SOD by default, unless
explicitly requested by user.
Since last mails, I've thought about this. I see one potential problem with
direct registry usage: global lock contention, i.e. users interested in
different services will affect each other. I have the following scenario in
mind:
1. Create one tracker (on bundle start maybe).
2. Use service via the same tracker concurrently from multiple threads.
3. Destroy the tracker (on bundle stop maybe).
By design, users of different services use different trackers, global lock
contention is reduced into per tracker lock contention. Furthermore,
performance of concurrent use of the same tracker can be further improved by
using read-write lock instead of the tracker lock.
However, current tracker implementation is sub-optimal: currently there is
no way to obtain opaque tracker pointer, only the tracker id is returned. The
translation between tracker id and opaque tracker pointer involves bundle
context lock. Thus our design only reduces global lock contention into per
bundle lock contention, not the optimal per tracker lock contention. If we can
get opaque tracker pointer from tracker id (service tracker is still created on
the event loop), then
`celix_serviceTracker_useHighestRankingService`/`celix_serviceTracker_useHighestRankingService`
can help us achieving optimal performance. Since no event loop is involved in
`celix_serviceTracker_useHighestRankingService`, its recursive usage (using a
service itself calling useService) together with async API may not hurt us any
more. IIRC, the intention of original OSGi service tracker is to avoid
external synchronization implemented by user. By re-exposing
`celix_serviceTracker_useHighestRankingService`
as public API, we can recovery its original design purpose.
I planed to discuss it with you after the release happens, since it involves
public API change bigger than this PR.
PS: Currently I'm working on conan support. Hopefully, a PR will arrive this
week. @pnoltes
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]