diff --git a/smocore/deviceManager/deviceManager.cpp b/smocore/deviceManager/deviceManager.cpp index 68bd634..fa4967a 100644 --- a/smocore/deviceManager/deviceManager.cpp +++ b/smocore/deviceManager/deviceManager.cpp @@ -44,21 +44,22 @@ const std::string DeviceManager::stringifyDeviceSpecs(void) } class DeviceManager::NewDeviceAttachmentSpecInd -: public PostedAsynchronousContinuation +: public SerializedAsynchronousContinuation { public: NewDeviceAttachmentSpecInd( - const std::shared_ptr &s, - const std::shared_ptr &d, + const DeviceAttachmentSpec &spec, const std::shared_ptr &caller, - Callback cb) - : PostedAsynchronousContinuation( - caller, cb), - spec(s), device(d) + Callback cb, + std::vector> requiredLocks) + : SerializedAsynchronousContinuation( + caller, cb, requiredLocks), + spec(spec) {} public: - std::shared_ptr spec; + DeviceAttachmentSpec spec; + std::shared_ptr specPtr; std::shared_ptr device; public: @@ -66,8 +67,73 @@ public: [[maybe_unused]] std::shared_ptr context ) { + // First, add the spec to deviceAttachmentSpecs if it's not already there + bool specExists = false; + for (const auto& existingSpec : DeviceManager::deviceAttachmentSpecs) + { + if (*existingSpec == spec) + { + specExists = true; + specPtr = existingSpec; + break; + } + } + + if (!specExists) + { + specPtr = std::make_shared(spec); + DeviceManager::deviceAttachmentSpecs.push_back(specPtr); + } + + bool deviceExists = false; + for (const auto& existingDevice : DeviceManager::devices) + { + if (existingDevice->deviceIdentifier != spec.deviceIdentifier) + { continue; } + + device = existingDevice; + deviceExists = true; + break; + } + + // If device doesn't exist, create a new one and add it + if (!device) + { + device = std::make_shared(spec.deviceIdentifier); + DeviceManager::devices.push_back(device); + } + + // Check if a DeviceRole w/ this spec already exists in attachedDeviceRoles + bool deviceRoleExists = false; + std::shared_ptr existingDeviceRole = nullptr; + for (const auto& role : DeviceManager::attachedDeviceRoles) + { + if (*role->deviceAttachmentSpec == spec) + { + deviceRoleExists = true; + existingDeviceRole = role; + break; + } + } + + // If DeviceRole exists, both spec and device must also exist + if (deviceRoleExists) + { + if (!specExists || !deviceExists) + { + throw std::runtime_error( + "Program error: DeviceRole exists but spec or device doesn't " + "pre-exist. specExists=" + std::to_string(specExists) + + ", deviceExists=" + std::to_string(deviceExists)); + } + + // Already attached, callback with success and return + callOriginalCb(true, existingDeviceRole, specPtr); + return; + } + DeviceManager::getInstance().attachSenseDeviceReq( - spec, + specPtr, {context, std::bind( &NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd2, context.get(), context, @@ -90,15 +156,15 @@ public: try { // Create DeviceRole and add it to both DeviceManager's and Device's collections - auto deviceRole = std::make_shared(*device, spec); + auto deviceRole = std::make_shared(*device, specPtr); device->deviceRoles.push_back(deviceRole); - attachedDeviceRoles.push_back(deviceRole); + DeviceManager::attachedDeviceRoles.push_back(deviceRole); // Callback with success - callOriginalCb(true, deviceRole, spec); + callOriginalCb(true, deviceRole, specPtr); } catch (const std::exception& e) { // Attach failed, callback with error - callOriginalCb(false, nullptr, spec); + callOriginalCb(false, nullptr, specPtr); } } }; @@ -205,82 +271,19 @@ void DeviceManager::newDeviceAttachmentSpecInd( const DeviceAttachmentSpec &spec, Callback callback) { - // First, add the spec to deviceAttachmentSpecs if it's not already there - bool specExists = false; - std::shared_ptr specPtr = nullptr; - for (const auto& existingSpec : deviceAttachmentSpecs) - { - if (*existingSpec == spec) - { - specExists = true; - specPtr = existingSpec; - break; - } - } - - if (!specExists) - { - specPtr = std::make_shared(spec); - deviceAttachmentSpecs.push_back(specPtr); - } - - bool deviceExists = false; - std::shared_ptr device = nullptr; - for (const auto& existingDevice : devices) - { - if (existingDevice->deviceIdentifier != spec.deviceIdentifier) - { continue; } - - device = existingDevice; - deviceExists = true; - break; - } - - // If device doesn't exist, create a new one and add it - if (!device) - { - device = std::make_shared(spec.deviceIdentifier); - devices.push_back(device); - } - - // Check if a DeviceRole w/ this spec already exists in attachedDeviceRoles - bool deviceRoleExists = false; - std::shared_ptr existingDeviceRole = nullptr; - for (const auto& role : attachedDeviceRoles) - { - if (*role->deviceAttachmentSpec == spec) - { - deviceRoleExists = true; - existingDeviceRole = role; - break; - } - } - - // If DeviceRole exists, both spec and device must also exist - if (deviceRoleExists) - { - if (!specExists || !deviceExists) - { - throw std::runtime_error( - "Program error: DeviceRole exists but spec or device doesn't " - "pre-exist. specExists=" + std::to_string(specExists) + - ", deviceExists=" + std::to_string(deviceExists)); - } - - // Already attached, callback with success - callback.callbackFn(true, existingDeviceRole, specPtr); - return; - } - - // Create async continuation const auto& caller = ComponentThread::getSelf(); - auto continuation = std::make_shared( - specPtr, device, caller, callback); - mrntt::mrntt.thread->getIoService().post( + auto request = std::make_shared( + spec, caller, callback, + LockSet::Set{ + std::ref(DeviceManager::getInstance().qutex) + }); + + NewDeviceAttachmentSpecInd::LockerAndInvoker lockvoker( + *request, mrntt::mrntt.thread, std::bind( &NewDeviceAttachmentSpecInd::newDeviceAttachmentSpecInd1_posted, - continuation.get(), continuation)); + request.get(), request)); } void DeviceManager::removeDeviceAttachmentSpecReq(