This is an automated email from the ASF dual-hosted git repository. pengzheng pushed a commit to branch feature/574-scope-based-resource-management in repository https://gitbox.apache.org/repos/asf/celix.git
commit a769a75c63eb438c72481d3fad32cd7883d7fe8a Author: PengZheng <[email protected]> AuthorDate: Mon Jul 31 22:01:17 2023 +0800 Unify naming convention for guard objects. --- .../src/discovery_zeroconf_announcer.c | 7 +- .../rsa_shm/src/rsa_shm_client.c | 34 +++--- .../rsa_shm/src/rsa_shm_export_registration.c | 12 +- .../rsa_shm/src/rsa_shm_impl.c | 16 ++- .../shm_pool/include/shm_pool.h | 30 +++-- .../rsa_rpc_json/src/rsa_json_rpc_endpoint_impl.c | 4 +- documents/c_patterns.md | 4 +- libs/framework/include/celix_bundle_context.h | 27 ++++- libs/framework/include_deprecated/bundle_context.h | 26 ++++- .../gtest/src/CelixUtilsAutoCleanupTestSuite.cc | 12 +- libs/utils/include/celix_threads.h | 125 ++++++++++++--------- 11 files changed, 182 insertions(+), 115 deletions(-) diff --git a/bundles/remote_services/discovery_zeroconf/src/discovery_zeroconf_announcer.c b/bundles/remote_services/discovery_zeroconf/src/discovery_zeroconf_announcer.c index f1429441..c79d1d1e 100644 --- a/bundles/remote_services/discovery_zeroconf/src/discovery_zeroconf_announcer.c +++ b/bundles/remote_services/discovery_zeroconf/src/discovery_zeroconf_announcer.c @@ -145,11 +145,8 @@ celix_status_t discoveryZeroconfAnnouncer_create(celix_bundle_context_t *ctx, ce celix_logHelper_fatal(logHelper, "Announcer: Failed to register endpoint listener."); return CELIX_BUNDLE_EXCEPTION; } - celix_auto(celix_service_reg_t) epListenerSvcReg = { - .ctx = ctx, - .svcId = announcer->epListenerSvcId - }; - + celix_auto(celix_service_registration_guard_t) epListenerSvcReg + = celix_serviceRegistrationGuard_init(ctx, announcer->epListenerSvcId); announcer->running = true; status = celixThread_create(&announcer->refreshEPThread, NULL, discoveryZeroconfAnnouncer_refreshEndpointThread, announcer); if (status != CELIX_SUCCESS) { diff --git a/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_client.c b/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_client.c index 280fcdbc..12a9e3ed 100644 --- a/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_client.c +++ b/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_client.c @@ -215,7 +215,7 @@ celix_status_t rsaShmClientManager_createOrAttachClient(rsa_shm_client_manager_t if (clientManager == NULL || peerServerName == NULL) { return CELIX_ILLEGAL_ARGUMENT; } - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&clientManager->clientsMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&clientManager->clientsMutex); rsa_shm_client_t *client = (rsa_shm_client_t *)celix_stringHashMap_get(clientManager->clients, peerServerName); if (client == NULL) { status = rsaShmClientManager_createClient(clientManager, peerServerName, &client); @@ -235,7 +235,7 @@ void rsaShmClientManager_destroyOrDetachClient(rsa_shm_client_manager_t *clientM if (clientManager == NULL || peerServerName == NULL) { return; } - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&clientManager->clientsMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&clientManager->clientsMutex); rsa_shm_client_t *client = (rsa_shm_client_t *)celix_stringHashMap_get(clientManager->clients, peerServerName); if (client != NULL) { rsaShmClient_destroyOrDetachSvcDiagInfo(client, serviceId); @@ -299,7 +299,8 @@ celix_status_t rsaShmClientManager_sendMsgTo(rsa_shm_client_manager_t *clientMan return status; } msgCtrl = (rsa_shm_msg_control_t*)msgCtrlAlloc.ctrl; - celix_auto(celix_shm_pool_alloc_t) msgBodyAlloc = celix_shmPool_malloc(clientManager->shmPool, msgBodySize); + celix_auto(celix_shm_pool_alloc_guard_t) msgBodyAlloc = + celix_shmPoolAllocGuard_init(shmPool_malloc(clientManager->shmPool, msgBodySize), clientManager->shmPool); char *msgBody = (char *)msgBodyAlloc.ptr; if (msgBody == NULL) { celix_logHelper_error(clientManager->logHelper, "RsaShmClient: Error allocing msg buffer."); @@ -445,7 +446,7 @@ static void rsaShmClientManager_destroyClient(rsa_shm_client_t *client) { static rsa_shm_client_t * rsaShmClientManager_getClient(rsa_shm_client_manager_t *clientManager, const char *peerServerName) { - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&clientManager->clientsMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&clientManager->clientsMutex); rsa_shm_client_t *client = (rsa_shm_client_t *)celix_stringHashMap_get(clientManager->clients, peerServerName); if (client != NULL) { client->refCnt ++; @@ -455,7 +456,7 @@ static rsa_shm_client_t * rsaShmClientManager_getClient(rsa_shm_client_manager_t static void rsaShmClientManager_ungetClient(rsa_shm_client_t *client) { rsa_shm_client_manager_t *clientManager = client->manager; - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&clientManager->clientsMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&clientManager->clientsMutex); client->refCnt--; if (client->refCnt == 0) { (void)celix_stringHashMap_remove(clientManager->clients, client->peerServerName); @@ -467,10 +468,10 @@ static void rsaShmClientManager_ungetClient(rsa_shm_client_t *client) { static void rsaShmClientManager_markSvcCallFailed(rsa_shm_client_manager_t *clientManager, const char *peerServerName, long serviceId) { - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&clientManager->clientsMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&clientManager->clientsMutex); rsa_shm_client_t *client = (rsa_shm_client_t *)celix_stringHashMap_get(clientManager->clients, peerServerName); if (client != NULL) { - celix_autoptr(celix_mutex_locker_t) diagInfoLocker = celixThreadMutexLocker_new(&client->diagInfoMutex); + celix_auto(celix_mutex_lock_guard_t) diagInfoLocker = celixMutexLockGuard_init(&client->diagInfoMutex); struct service_diagnostic_info *svcDiagInfo = (struct service_diagnostic_info *) celix_longHashMap_get(client->svcDiagInfo, serviceId); if (svcDiagInfo != NULL) { @@ -481,10 +482,10 @@ static void rsaShmClientManager_markSvcCallFailed(rsa_shm_client_manager_t *clie static void rsaShmClientManager_markSvcCallFinished(rsa_shm_client_manager_t *clientManager, const char *peerServerName, long serviceId) { - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&clientManager->clientsMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&clientManager->clientsMutex); rsa_shm_client_t *client = (rsa_shm_client_t *)celix_stringHashMap_get(clientManager->clients, peerServerName); if (client != NULL) { - celix_autoptr(celix_mutex_locker_t) diagInfoLocker = celixThreadMutexLocker_new(&client->diagInfoMutex); + celix_auto(celix_mutex_lock_guard_t) diagInfoLocker = celixMutexLockGuard_init(&client->diagInfoMutex); struct service_diagnostic_info *svcDiagInfo = (struct service_diagnostic_info *) celix_longHashMap_get(client->svcDiagInfo, serviceId); if (svcDiagInfo != NULL) { @@ -499,7 +500,8 @@ static celix_status_t rsaShmClientManager_createMsgControl(rsa_shm_client_manage assert(alloc != NULL); int retVal = 0; alloc->clientManager = clientManager; - celix_auto(celix_shm_pool_alloc_t) allocRes = celix_shmPool_malloc(clientManager->shmPool, sizeof(rsa_shm_msg_control_t)); + celix_auto(celix_shm_pool_alloc_guard_t) allocRes = celix_shmPoolAllocGuard_init( + shmPool_malloc(clientManager->shmPool, sizeof(rsa_shm_msg_control_t)), clientManager->shmPool); rsa_shm_msg_control_t *msgCtrl = (rsa_shm_msg_control_t *)allocRes.ptr; if (msgCtrl == NULL) { return ENOMEM; @@ -551,7 +553,7 @@ static bool rsaShmClientManager_handleMsgState(rsa_shm_client_manager_t *clientM bool removed = false; bool signal = false; rsa_shm_msg_control_t *ctrl = msgEntry->msgCtrl; - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&ctrl->lock); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&ctrl->lock); switch (ctrl->msgState) { case REQUESTING: case REPLYING: @@ -581,7 +583,7 @@ static void *rsaShmClientManager_exceptionMsgHandlerThread(void *data) { bool removed = false; celix_autoptr(celix_array_list_t) evictedMsgs = celix_arrayList_create(); while (active) { - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&clientManager->exceptionMsgListMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&clientManager->exceptionMsgListMutex); listSize = celix_arrayList_size(clientManager->exceptionMsgList); for (int i = 0; i < listSize; ++i) { struct rsa_shm_exception_msg *exceptionMsg = celix_arrayList_get(clientManager->exceptionMsgList, i); @@ -633,7 +635,7 @@ static celix_status_t rsaShmClientManager_receiveResponse(rsa_shm_client_manager *replied = false; do { isStreamingReply = false; - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&msgCtrl->lock); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&msgCtrl->lock); while (msgCtrl->msgState == REQUESTING && waitRet == 0) { //pthread_cond_timedwait shall not return an error code of [EINTR]. refer https://man7.org/linux/man-pages/man3/pthread_cond_timedwait.3p.html waitRet = pthread_cond_timedwait(&msgCtrl->signal, &msgCtrl->lock, &timeout); @@ -679,7 +681,7 @@ static celix_status_t rsaShmClientManager_receiveResponse(rsa_shm_client_manager } static void rsaShmClient_createOrAttachSvcDiagInfo(rsa_shm_client_t *client, long serviceId) { - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&client->diagInfoMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&client->diagInfoMutex); struct service_diagnostic_info *svcDiagInfo = (struct service_diagnostic_info *) celix_longHashMap_get(client->svcDiagInfo, serviceId); if (svcDiagInfo == NULL) { @@ -695,7 +697,7 @@ static void rsaShmClient_createOrAttachSvcDiagInfo(rsa_shm_client_t *client, lon } static void rsaShmClient_destroyOrDetachSvcDiagInfo(rsa_shm_client_t *client, long serviceId) { - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&client->diagInfoMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&client->diagInfoMutex); struct service_diagnostic_info *svcDiagInfo = (struct service_diagnostic_info *) celix_longHashMap_get(client->svcDiagInfo, serviceId); if (--svcDiagInfo->refCnt == 0) { @@ -708,7 +710,7 @@ static void rsaShmClient_destroyOrDetachSvcDiagInfo(rsa_shm_client_t *client, lo static bool rsaShmClient_shouldBreakInvocation(rsa_shm_client_t *client, long serviceId) { bool breaked = false; rsa_shm_client_manager_t *clientManager = client->manager; - celix_autoptr(celix_mutex_locker_t) locker = celixThreadMutexLocker_new(&client->diagInfoMutex); + celix_auto(celix_mutex_lock_guard_t) locker = celixMutexLockGuard_init(&client->diagInfoMutex); do { struct service_diagnostic_info *svcDiagInfo = (struct service_diagnostic_info *) celix_longHashMap_get(client->svcDiagInfo, serviceId); diff --git a/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_export_registration.c b/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_export_registration.c index 70d37fe1..e86bcf7e 100644 --- a/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_export_registration.c +++ b/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_export_registration.c @@ -100,11 +100,7 @@ celix_status_t exportRegistration_create(celix_bundle_context_t *context, celix_logHelper_error(logHelper,"RSA export reg: Retain refrence for %s failed. %d.", endpointDesc->serviceName, status); return status; } - celix_auto(celix_service_ref_t) ref = { - .reference = reference, - .context = context, - }; - + celix_auto(celix_service_ref_guard_t) ref = celix_ServiceRefGuard_init(context, reference); celix_autoptr(export_request_handler_service_entry_t) reqHandlerSvcEntry = exportRegistration_createReqHandlerSvcEntry(); if (reqHandlerSvcEntry == NULL) { celix_logHelper_error(export->logHelper,"RSA export reg: Error creating endpoint svc entry."); @@ -296,7 +292,7 @@ static void exportRegistration_addRequestHandlerSvc(void *handle, void *svc) { assert(svc != NULL); struct export_request_handler_service_entry *reqHandlerSvcEntry = (struct export_request_handler_service_entry *)handle; - celix_autoptr(celix_rwlock_writer_locker_t) locker = celixThreadRwlockWriterLocker_new(&reqHandlerSvcEntry->lock); + celix_auto(celix_rwlock_wlock_guard_t) locker = celixRwlockWlockGuard_init(&reqHandlerSvcEntry->lock); reqHandlerSvcEntry->reqHandlerSvc = (rsa_request_handler_service_t *)svc; return; } @@ -306,7 +302,7 @@ static void exportRegistration_removeRequestHandlerSvc(void *handle, void *svc) assert(svc != NULL); struct export_request_handler_service_entry *reqHandlerSvcEntry = (struct export_request_handler_service_entry *)handle; - celix_autoptr(celix_rwlock_writer_locker_t) locker = celixThreadRwlockWriterLocker_new(&reqHandlerSvcEntry->lock); + celix_auto(celix_rwlock_wlock_guard_t) locker = celixRwlockWlockGuard_init(&reqHandlerSvcEntry->lock); if (svc == reqHandlerSvcEntry->reqHandlerSvc) { reqHandlerSvcEntry->reqHandlerSvc = NULL; } @@ -321,7 +317,7 @@ celix_status_t exportRegistration_call(export_registration_t *export, celix_prop } struct export_request_handler_service_entry *reqHandlerSvcEntry = export->reqHandlerSvcEntry; assert(reqHandlerSvcEntry != NULL); - celix_autoptr(celix_rwlock_reader_locker_t) locker = celixThreadRwlockReaderLocker_new(&reqHandlerSvcEntry->lock); + celix_auto(celix_rwlock_rlock_guard_t) locker = celixRwlockRlockGuard_init(&reqHandlerSvcEntry->lock); if (reqHandlerSvcEntry->reqHandlerSvc != NULL) { status = reqHandlerSvcEntry->reqHandlerSvc->handleRequest(reqHandlerSvcEntry->reqHandlerSvc->handle, metadata, request, response); } else { diff --git a/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_impl.c b/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_impl.c index 63c504fe..fcab1ecb 100755 --- a/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_impl.c +++ b/bundles/remote_services/remote_service_admin_shm_v2/rsa_shm/src/rsa_shm_impl.c @@ -111,7 +111,8 @@ celix_status_t rsaShm_create(celix_bundle_context_t *context, celix_log_helper_t celix_logHelper_error(logHelper,"Error registering request sender service."); return CELIX_BUNDLE_EXCEPTION; } - celix_auto(celix_service_reg_t) reg = { .ctx = context, .svcId = ad->reqSenderSvcId }; + celix_auto(celix_service_registration_guard_t) reg = + celix_serviceRegistrationGuard_init(context, ad->reqSenderSvcId); const char *fwUuid = celix_bundleContext_getProperty(context, OSGI_FRAMEWORK_FRAMEWORK_UUID, NULL); if (fwUuid == NULL) { @@ -167,7 +168,7 @@ void rsaShm_destroy(rsa_shm_t *admin) { } static export_registration_t* rsaShm_getExportService(rsa_shm_t *admin, long serviceId) { - celix_autoptr(celix_mutex_locker_t) lock = celixThreadMutexLocker_new(&admin->exportedServicesLock); + celix_auto(celix_mutex_lock_guard_t) lock = celixMutexLockGuard_init(&admin->exportedServicesLock); export_registration_t *export = NULL; celix_array_list_t *exports = celix_longHashMap_get(admin->exportedServices, serviceId); if (exports != NULL && celix_arrayList_size(exports) > 0) { @@ -306,10 +307,7 @@ celix_status_t rsaShm_exportService(rsa_shm_t *admin, char *serviceId, celix_logHelper_error(admin->logHelper, "Expect a reference for service id %s.", serviceId); return CELIX_ILLEGAL_STATE; } - celix_auto(celix_service_ref_t) ref = { - .reference = reference, - .context = admin->context - }; + celix_auto(celix_service_ref_guard_t) ref = celix_ServiceRefGuard_init(admin->context, reference); celix_autoptr(celix_properties_t) exportedProperties = celix_properties_create(); if (exportedProperties == NULL) { @@ -412,7 +410,7 @@ celix_status_t rsaShm_exportService(rsa_shm_t *admin, char *serviceId, for (int i = 0; i < regSize; ++i) { celix_arrayList_add(newRegistrations, celix_arrayList_get(registrations, i)); } - celix_autoptr(celix_mutex_locker_t) lock = celixThreadMutexLocker_new(&admin->exportedServicesLock); + celix_auto(celix_mutex_lock_guard_t) lock = celixMutexLockGuard_init(&admin->exportedServicesLock); celix_longHashMap_put(admin->exportedServices, atol(serviceId), celix_steal_ptr(registrations)); } *registrationsOut = newRegistrations; @@ -615,7 +613,7 @@ celix_status_t rsaShm_importService(rsa_shm_t *admin, endpoint_description_t *en return status; } - celix_autoptr(celix_mutex_locker_t) lock = celixThreadMutexLocker_new(&admin->importedServicesLock); + celix_auto(celix_mutex_lock_guard_t) lock = celixMutexLockGuard_init(&admin->importedServicesLock); celix_arrayList_add(admin->importedServices, import); *registration = import; return CELIX_SUCCESS; @@ -642,7 +640,7 @@ celix_status_t rsaShm_removeImportedService(rsa_shm_t *admin, import_registratio celix_logHelper_error(admin->logHelper, "Error getting endpoint from imported registration for service %s. It maybe cause resource leaks.", endpoint->serviceName); } - celix_autoptr(celix_mutex_locker_t) lock = celixThreadMutexLocker_new(&admin->importedServicesLock); + celix_auto(celix_mutex_lock_guard_t) lock = celixMutexLockGuard_init(&admin->importedServicesLock); celix_arrayList_remove(admin->importedServices, registration); importRegistration_destroy(registration); diff --git a/bundles/remote_services/remote_service_admin_shm_v2/shm_pool/include/shm_pool.h b/bundles/remote_services/remote_service_admin_shm_v2/shm_pool/include/shm_pool.h index d89f963b..d4416217 100644 --- a/bundles/remote_services/remote_service_admin_shm_v2/shm_pool/include/shm_pool.h +++ b/bundles/remote_services/remote_service_admin_shm_v2/shm_pool/include/shm_pool.h @@ -85,23 +85,37 @@ void shmPool_free(shm_pool_t *pool, void *ptr); */ ssize_t shmPool_getMemoryOffset(shm_pool_t *pool, void *ptr); -typedef struct celix_shm_pool_alloc { +/** + * @brief Scoped guard for shared memory pool allocation. + */ +typedef struct celix_shm_pool_alloc_guard { void* ptr; shm_pool_t* pool; -} celix_shm_pool_alloc_t; +} celix_shm_pool_alloc_guard_t; -static CELIX_UNUSED inline celix_shm_pool_alloc_t celix_shmPool_malloc(shm_pool_t *pool, size_t size) { - return (celix_shm_pool_alloc_t) { - .ptr = shmPool_malloc(pool, size), +/** + * @brief Initialize a shared memory pool allocation guard. + * @param [in] addr Start address of the allocated memory. + * @param [in] pool The shared memory pool. + * @return An initialized guard. + */ +static CELIX_UNUSED inline celix_shm_pool_alloc_guard_t celix_shmPoolAllocGuard_init(void* addr, shm_pool_t* pool) { + return (celix_shm_pool_alloc_guard_t) { + .ptr = addr, .pool = pool }; } -static CELIX_UNUSED inline void celix_shmPool_free(celix_shm_pool_alloc_t* alloc) { - shmPool_free(alloc->pool, alloc->ptr); +/** + * @brief Deinitialize a shared memory pool allocation guard. + * The guard will free the allocated memory. + * @param [in] guard The guard to deinitialize. + */ +static CELIX_UNUSED inline void celix_shmPoolAllocGuard_deinit(celix_shm_pool_alloc_guard_t* guard) { + shmPool_free(guard->pool, guard->ptr); } -CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_shm_pool_alloc_t, celix_shmPool_free) +CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_shm_pool_alloc_guard_t, celix_shmPoolAllocGuard_deinit) #ifdef __cplusplus } diff --git a/bundles/remote_services/rsa_rpc_json/src/rsa_json_rpc_endpoint_impl.c b/bundles/remote_services/rsa_rpc_json/src/rsa_json_rpc_endpoint_impl.c index 1e2fa862..ee1dc5ef 100644 --- a/bundles/remote_services/rsa_rpc_json/src/rsa_json_rpc_endpoint_impl.c +++ b/bundles/remote_services/rsa_rpc_json/src/rsa_json_rpc_endpoint_impl.c @@ -162,7 +162,7 @@ static void rsaJsonRpcEndpoint_addSvcWithOwner(void *handle, void *service, celix_autoptr(dyn_interface_type) intfType = NULL; const char *serviceName = celix_properties_get(endpoint->endpointDesc->properties, CELIX_FRAMEWORK_SERVICE_NAME, "unknown-service"); - celix_autoptr(celix_rwlock_writer_locker_t) lock = celixThreadRwlockWriterLocker_new(&endpoint->lock); + celix_auto(celix_rwlock_wlock_guard_t) lock = celixRwlockWlockGuard_init(&endpoint->lock); status = dfi_findAndParseInterfaceDescriptor(endpoint->logHelper,endpoint->ctx, svcOwner, endpoint->endpointDesc->serviceName, &intfType); @@ -200,7 +200,7 @@ static void rsaJsonRpcEndpoint_removeSvcWithOwner(void *handle, void *service, (void)props; (void)svcOwner; rsa_json_rpc_endpoint_t *endpoint = (rsa_json_rpc_endpoint_t *)handle; - celix_autoptr(celix_rwlock_writer_locker_t) lock = celixThreadRwlockWriterLocker_new(&endpoint->lock); + celix_auto(celix_rwlock_wlock_guard_t) lock = celixRwlockWlockGuard_init(&endpoint->lock); if (endpoint->service == service) { endpoint->service = NULL; dynInterface_destroy(endpoint->intfType); diff --git a/documents/c_patterns.md b/documents/c_patterns.md index 81f7297f..054ca815 100644 --- a/documents/c_patterns.md +++ b/documents/c_patterns.md @@ -75,8 +75,8 @@ used to guard locks, manage service registration, etc. Support for RAII-like str additional cleanup functions that work with either the `celix_auto` or `celix_autoptr` macros. Examples include: -- `celixThreadMutexLocker_new` -- `celix_service_reg_t` +- `celix_mutex_lock_guard_t` +- `celix_service_registration_guard_t` Special effort is made to ensure that these constructs do not require additional allocation and should provide minimal to no additional overhead. diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h index 8f568c9d..f68700f1 100644 --- a/libs/framework/include/celix_bundle_context.h +++ b/libs/framework/include/celix_bundle_context.h @@ -274,18 +274,37 @@ CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_isServiceRegistered(celix_bundle */ CELIX_FRAMEWORK_EXPORT void celix_bundleContext_unregisterService(celix_bundle_context_t *ctx, long serviceId); -typedef struct celix_service_reg { +/** + * @brief Service registration guard. + */ +typedef struct celix_service_registration_guard { celix_bundle_context_t* ctx; long svcId; -} celix_service_reg_t; +} celix_service_registration_guard_t; + +/** + * @brief Initialize a a scode guard for an existing service registration. + * @param [in] ctx The bundle context associated with the service registration. + * @param [in] serviceId The service id. + * @return An initialized service registration guard. + */ +static CELIX_UNUSED inline celix_service_registration_guard_t +celix_serviceRegistrationGuard_init(celix_bundle_context_t* ctx, long serviceId) { + return (celix_service_registration_guard_t) { .ctx = ctx, .svcId = serviceId }; +} -static CELIX_UNUSED inline void celix_service_unregister(celix_service_reg_t* reg) { +/** + * @brief Deinitialize a service registration guard. + * Will unregister the service if the service id is >= 0. + * @param [in] reg A service registration guard + */ +static CELIX_UNUSED inline void celix_serviceRegistrationGuard_deinit(celix_service_registration_guard_t* reg) { if (reg->svcId >= 0) { celix_bundleContext_unregisterService(reg->ctx, reg->svcId); } } -CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_service_reg_t, celix_service_unregister) +CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_service_registration_guard_t, celix_serviceRegistrationGuard_deinit) /** * @brief Unregister the service or service factory with service id. diff --git a/libs/framework/include_deprecated/bundle_context.h b/libs/framework/include_deprecated/bundle_context.h index 866e9914..1ee6bfe3 100644 --- a/libs/framework/include_deprecated/bundle_context.h +++ b/libs/framework/include_deprecated/bundle_context.h @@ -120,19 +120,37 @@ bundleContext_retainServiceReference(celix_bundle_context_t *context, service_re CELIX_FRAMEWORK_DEPRECATED_EXPORT celix_status_t bundleContext_ungetServiceReference(celix_bundle_context_t *context, service_reference_pt reference); -typedef struct celix_service_ref { +/** + * @brief Service reference guard. + */ +typedef struct celix_service_ref_guard { service_reference_pt reference; celix_bundle_context_t* context; -} celix_service_ref_t; +} celix_service_ref_guard_t; +/** + * @brief Initialize a scope guard for an existing reference. + * @param [in] context Bundle owner of the service reference. + * @param [in] reference An existing service reference. + * @return An initialized service reference guard. + */ +static CELIX_UNUSED inline celix_service_ref_guard_t celix_ServiceRefGuard_init(celix_bundle_context_t* context, + service_reference_pt reference) { + return (celix_service_ref_guard_t){.reference = reference, .context = context}; +} -static CELIX_UNUSED inline void celix_ServiceRef_put(celix_service_ref_t* ref) { +/** + * @brief Deinitialize a service reference guard. + * Ungets the contained service reference if it is not NULL. + * @param [in] ref A service reference guard. + */ +static CELIX_UNUSED inline void celix_ServiceRefGuard_deinit(celix_service_ref_guard_t* ref) { if (ref->reference != NULL) { bundleContext_ungetServiceReference(ref->context, ref->reference); } } -CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_service_ref_t, celix_ServiceRef_put); +CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_service_ref_guard_t, celix_ServiceRefGuard_deinit); CELIX_FRAMEWORK_DEPRECATED_EXPORT celix_status_t bundleContext_getService(celix_bundle_context_t *context, service_reference_pt reference, void **service_instance); diff --git a/libs/utils/gtest/src/CelixUtilsAutoCleanupTestSuite.cc b/libs/utils/gtest/src/CelixUtilsAutoCleanupTestSuite.cc index 911c6ac9..47fbc697 100644 --- a/libs/utils/gtest/src/CelixUtilsAutoCleanupTestSuite.cc +++ b/libs/utils/gtest/src/CelixUtilsAutoCleanupTestSuite.cc @@ -85,8 +85,8 @@ TEST_F(CelixUtilsCleanupTestSuite, MutexLockerTest) { celix_thread_t thread = celix_thread_default; EXPECT_EQ(0, celixThreadMutex_create(&mutex, nullptr)); if (true) { - celix_autoptr(celix_mutex_locker_t) val = celixThreadMutexLocker_new(&mutex); - ASSERT_NE(nullptr, val); + celix_auto(celix_mutex_lock_guard_t) val = celixMutexLockGuard_init(&mutex); + ASSERT_NE(nullptr, val.mutex); // Verify that the mutex is actually locked celixThread_create(&thread, nullptr, mutexLockedThread, &mutex); @@ -125,8 +125,8 @@ TEST_F(CelixUtilsCleanupTestSuite, RwLockLockerTest) { ASSERT_EQ(0, celixThreadRwlock_create(&lock, nullptr)); if (true) { - celix_autoptr(celix_rwlock_writer_locker_t) val = celixThreadRwlockWriterLocker_new(&lock); - ASSERT_NE(nullptr, val); + celix_auto(celix_rwlock_wlock_guard_t) val = celixRwlockWlockGuard_init(&lock); + ASSERT_NE(nullptr, val.lock); /* Verify that we cannot take another writer lock as a writer lock is currently held */ celixThread_create(&thread, nullptr, rwlockCannotTakeWriterLockThread, &lock); @@ -136,8 +136,8 @@ TEST_F(CelixUtilsCleanupTestSuite, RwLockLockerTest) { EXPECT_NE(0, celixThreadRwlock_tryReadLock(&lock)); } if (true) { - celix_autoptr(celix_rwlock_reader_locker_t) val = celixThreadRwlockReaderLocker_new(&lock); - ASSERT_NE(nullptr, val); + celix_auto(celix_rwlock_rlock_guard_t) val = celixRwlockRlockGuard_init(&lock); + ASSERT_NE(nullptr, val.lock); /* Verify that we can take another reader lock from another thread */ celixThread_create(&thread, nullptr, rwlockCanTakeReaderLockThread, &lock); diff --git a/libs/utils/include/celix_threads.h b/libs/utils/include/celix_threads.h index 18fe7a06..064601d7 100644 --- a/libs/utils/include/celix_threads.h +++ b/libs/utils/include/celix_threads.h @@ -104,40 +104,45 @@ CELIX_UTILS_EXPORT celix_status_t celixThreadMutex_tryLock(celix_thread_mutex_t CELIX_UTILS_EXPORT celix_status_t celixThreadMutex_unlock(celix_thread_mutex_t *mutex); /** - * Opaque type. See celix_mutex_locker_new() for details. + * @brief Lock guard for mutex. */ -typedef void celix_mutex_locker_t; +typedef struct celix_mutex_lock_guard { + celix_thread_mutex_t *mutex; +} celix_mutex_lock_guard_t; /** - * @brief Lock @a mutex and return a new celix_mutex_locker_t. + * @brief Initialize a lock guard for @a mutex. * - * Unlock with celixThreadMutexLocker_free(). Using celixThreadMutex_lock() on @a mutex - * while a celix_mutex_locker_t exists can lead to undefined behaviour. + * Lock @a mutex and return a celix_mutex_lock_guard_t. + * Unlock with celixMutexLockGuard_deinit(). Using celixThreadMutex_lock() on @a mutex + * while a celix_mutex_lock_guard_t exists can lead to undefined behaviour. * * No allocation is performed, it is equivalent to a celixThreadMutex_lock() call. - * This is intended to be used with celix_autoptr(). + * This is intended to be used with celix_auto(). * - * @param mutex A mutex to lock - * @return A new locker to be used with celix_autoptr(). + * @param mutex A mutex to lock. + * @return An initialized lock guard to be used with celix_auto(). */ -static inline celix_mutex_locker_t* celixThreadMutexLocker_new(celix_thread_mutex_t* mutex) { +static CELIX_UNUSED inline celix_mutex_lock_guard_t celixMutexLockGuard_init(celix_thread_mutex_t* mutex) { + celix_mutex_lock_guard_t guard; + guard.mutex = mutex; celixThreadMutex_lock(mutex); - return (celix_mutex_locker_t*)mutex; + return guard; } /** - * @brief Unlock the mutex of @a locker. + * @brief Deinitialize a lock guard for @a mutex. * - * See celixThreadMutexLocker_new() for details. + * Unlock the mutex of @a guard. * No memory is freed, it is equivalent to a celixThreadMutex_unlock() call. * - * @param locker A celix_mutex_locker_t + * @param guard A celix_mutex_lock_guard_t. */ -static inline void celixThreadMutexLocker_free(celix_mutex_locker_t* locker) { - celixThreadMutex_unlock((celix_thread_mutex_t*)locker); +static CELIX_UNUSED inline void celixMutexLockGuard_deinit(celix_mutex_lock_guard_t* guard) { + celixThreadMutex_unlock(guard->mutex); } -CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_mutex_locker_t, celixThreadMutexLocker_free) +CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_mutex_lock_guard_t, celixMutexLockGuard_deinit) CELIX_UTILS_EXPORT celix_status_t celixThreadMutexAttr_create(celix_thread_mutexattr_t *attr); @@ -167,76 +172,94 @@ CELIX_UTILS_EXPORT celix_status_t celixThreadRwlock_tryWriteLock(celix_thread_rw CELIX_UTILS_EXPORT celix_status_t celixThreadRwlock_unlock(celix_thread_rwlock_t *lock); /** - * Opaque type. See celixThreadRwlockWriterLocker_new() for details. + * @brief A RAII style write lock guard for celix_thread_rwlock_t. + * + * The lock is obtained in the constructor and released in the destructor. + * This is intended to be used with celix_auto(). */ -typedef void celix_rwlock_writer_locker_t; +typedef struct celix_rwlock_wlock_guard { + celix_thread_rwlock_t *lock; +} celix_rwlock_wlock_guard_t; /** - * @brief Obtain a write lock on @a rwLock and return a new celix_rwlock_writer_locker_t. + * @brief Initialize a write lock guard for @a lock. * - * Unlock with celixThreadRwlockWriterLocker_free(). Using celixThreadRwlock_unlock() - * on @a rwLock while a celix_rwlock_writer_locker_t exists can lead to undefined behaviour. + * Obtain a write lock on @a lock and return a celix_rwlock_wlock_guard_t. + * Unlock with celixRwlockWlockGuard_deinit(). Using celixThreadRwlock_unlock() + * on @lock while a celix_rwlock_rlock_guard_t exists can lead to undefined behaviour. * - * No allocation is performed, it is equivalent to a celixThreadRwlock_writeLock() call. - * This is intended to be used with celix_autoptr(). + * No allocation is performed, it is equivalent to a celixThreadRwlock_readLock() call. + * This is intended to be used with celix_auto(). * - * @param rwLock A read-write lock to lock. - * @return A new locker to be used with celix_autoptr(). + * @param lock A read-write lock to lock. + * @return An initialized write lock guard to be used with celix_auto(). */ -static inline celix_rwlock_writer_locker_t* celixThreadRwlockWriterLocker_new(celix_thread_rwlock_t* rwLock) { - celixThreadRwlock_writeLock(rwLock); - return (celix_rwlock_writer_locker_t*)rwLock; +static CELIX_UNUSED inline celix_rwlock_wlock_guard_t celixRwlockWlockGuard_init(celix_thread_rwlock_t* lock) { + celix_rwlock_wlock_guard_t guard; + guard.lock = lock; + celixThreadRwlock_writeLock(lock); + return guard; } /** - * @brief Release a write lock on the read-write lock of @a locker. + * @brief Deinitialize a write lock guard. * - * See celixThreadRwlockWriterLocker_new() for details. + * Release a write lock on the read-write lock contained in @a guard. + * See celixRwlockWlockGuard_init() for details. * No memory is freed, it is equivalent to a celixThreadRwlock_unlock() call. * - * @param locker A celix_rwlock_writer_locker_t. + * @param guard A celix_rwlock_wlock_guard_t. */ -static inline void celixThreadRwlockWriterLocker_free(celix_rwlock_writer_locker_t* locker) { - celixThreadRwlock_unlock((celix_thread_rwlock_t*)locker); +static CELIX_UNUSED inline void celixRwlockWlockGuard_deinit(celix_rwlock_wlock_guard_t* guard) { + celixThreadRwlock_unlock(guard->lock); } -CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_rwlock_writer_locker_t, celixThreadRwlockWriterLocker_free) +CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_rwlock_wlock_guard_t, celixRwlockWlockGuard_deinit) /** - * Opaque type. See celixThreadRwlockReaderLocker_new() for details. + * @brief A RAII style read lock guard for celix_thread_rwlock_t. + * + * The lock is obtained in the constructor and released in the destructor. + * This is intended to be used with celix_auto(). */ -typedef void celix_rwlock_reader_locker_t; +typedef struct celix_rwlock_rlock_guard { + celix_thread_rwlock_t *lock; +} celix_rwlock_rlock_guard_t; /** - * @brief Obtain a read lock on @a rwLock and return a new celix_rwlock_reader_locker_t. + * @brief Initialize a read lock guard for @a lock. * - * Unlock with celixThreadRwlockReaderLocker_free(). Using celixThreadRwlock_unlock() - * on @rwLock while a celix_rwlock_reader_locker_t exists can lead to undefined behaviour. + * Obtain a read lock on @a lock and return a celix_rwlock_rlock_guard_t. + * Unlock with celix_RwlockRlockGuard_deinit(). Using celixThreadRwlock_unlock() + * on @lock while a celix_rwlock_rlock_guard_t exists can lead to undefined behaviour. * * No allocation is performed, it is equivalent to a celixThreadRwlock_readLock() call. - * This is intended to be used with celix_autoptr(). + * This is intended to be used with celix_auto(). * - * @param rwLock A read-write lock to lock. - * @return A new locker to be used with celix_autoptr(). + * @param lock A read-write lock to lock. + * @return A guard to be used with celix_auto(). */ -static inline celix_rwlock_reader_locker_t* celixThreadRwlockReaderLocker_new(celix_thread_rwlock_t* rwLock) { - celixThreadRwlock_readLock(rwLock); - return (celix_rwlock_reader_locker_t*)rwLock; +static CELIX_UNUSED inline celix_rwlock_rlock_guard_t celixRwlockRlockGuard_init(celix_thread_rwlock_t *lock) { + celix_rwlock_rlock_guard_t guard; + guard.lock = lock; + celixThreadRwlock_readLock(lock); + return guard; } /** - * @brief Release a read lock on the read-write lock of @a locker. + * @brief Deinitialize a read lock guard. * - * See celixThreadRwlockReaderLocker_new() for details. + * Release a read lock on the read-write lock contained in @a guard. + * See celixRwlockRlockGuard_init() for details. * No memory is freed, it is equivalent to a celixThreadRwlock_unlock() call. * - * @param locker A celix_rwlock_reader_locker_t. + * @param guard A celix_rwlock_rlock_guard_t. */ -static inline void celixThreadRwlockReaderLocker_free(celix_rwlock_reader_locker_t* locker) { - celixThreadRwlock_unlock((celix_thread_rwlock_t*)locker); +static CELIX_UNUSED inline void celixRwlockRlockGuard_deinit(celix_rwlock_rlock_guard_t* guard) { + celixThreadRwlock_unlock(guard->lock); } -CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_rwlock_reader_locker_t, celixThreadRwlockReaderLocker_free) +CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_rwlock_rlock_guard_t, celixRwlockRlockGuard_deinit) CELIX_UTILS_EXPORT celix_status_t celixThreadRwlockAttr_create(celix_thread_rwlockattr_t *attr);
