diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index cf664a5e9fdeb..e3c29035e9d21 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -957,9 +957,12 @@ void DataProcessingDevice::InitTask() LOG(detail) << "ptr: " << info.ptr; LOG(detail) << "size: " << info.size; LOG(detail) << "flags: " << info.flags; - context.expectedRegionCallbacks -= 1; + // Now we check for pending events with the mutex, + // so the lines below are atomic. pendingRegionInfos.push_back(info); - // We always want to handle these on the main loop + context.expectedRegionCallbacks -= 1; + // We always want to handle these on the main loop, + // so we awake it. ServiceRegistryRef ref{registry}; uv_async_send(ref.get().awakeMainThread); }); @@ -991,11 +994,17 @@ void DataProcessingDevice::InitTask() // We will get there. this->fillContext(mServiceRegistry.get(ServiceRegistry::globalDeviceSalt()), deviceContext); + auto hasPendingEvents = [&mutex = mRegionInfoMutex, &pendingRegionInfos = mPendingRegionInfos](DeviceContext& deviceContext) { + std::lock_guard lock(mutex); + return (pendingRegionInfos.empty() == false) || deviceContext.expectedRegionCallbacks > 0; + }; /// We now run an event loop also in InitTask. This is needed to: /// * Make sure region registration callbacks are invoked /// on the main thread. /// * Wait for enough callbacks to be delivered before moving to START - while (deviceContext.expectedRegionCallbacks > 0 && uv_run(state.loop, UV_RUN_ONCE)) { + while (hasPendingEvents(deviceContext)) { + // Wait for the callback to signal its done, so that we do not busy wait. + uv_run(state.loop, UV_RUN_ONCE); // Handle callbacks if any { std::lock_guard lock(mRegionInfoMutex);