Mercurial > hg > orthanc-stone
changeset 2313:46e57967b285 refactoring
replacing ILoadersContext by StoneApplication
line wrap: on
line diff
--- a/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp Tue Sep 29 17:52:35 2026 +0200 +++ b/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp Wed Sep 30 11:50:48 2026 +0200 @@ -459,7 +459,7 @@ #endif boost::shared_ptr<SdlSimpleViewerApplication> application( - SdlSimpleViewerApplication::Create(context, viewport)); + SdlSimpleViewerApplication::Create(OrthancStone::StoneApplication::GetInstance(), viewport)); OrthancStone::DicomSource source;
--- a/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewerApplication.h Tue Sep 29 17:52:35 2026 +0200 +++ b/Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewerApplication.h Wed Sep 30 11:50:48 2026 +0200 @@ -27,6 +27,7 @@ #include "../../../../OrthancStone/Sources/Loaders/SeriesFramesLoader.h" #include "../../../../OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.h" #include "../../../../OrthancStone/Sources/Scene2DViewport/ViewportController.h" +#include "../../../../OrthancStone/Sources/StoneApplication.h" #include "../../../../OrthancStone/Sources/Viewport/IViewport.h" #include <Compatibility.h> // For std::unique_ptr<> @@ -55,14 +56,12 @@ { public: - static boost::shared_ptr<SdlSimpleViewerApplication> Create(ILoadersContext& context, boost::shared_ptr<IViewport> viewport) + static boost::shared_ptr<SdlSimpleViewerApplication> Create(OrthancStone::StoneApplication::Context& context, + boost::shared_ptr<IViewport> viewport) { boost::shared_ptr<SdlSimpleViewerApplication> application(new SdlSimpleViewerApplication(context, viewport)); - { - std::unique_ptr<ILoadersContext::ILock> lock(context.Lock()); - application->dicomLoader_ = DicomResourcesLoader::Create(*lock); - } + application->dicomLoader_ = DicomResourcesLoader::Create(context); application->Register<DicomResourcesLoader::SuccessMessage>(*application->dicomLoader_, &SdlSimpleViewerApplication::Handle); @@ -71,7 +70,7 @@ void LoadOrthancFrame(const DicomSource& source, const std::string& instanceId, unsigned int frame) { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); dicomLoader_->ScheduleLoadOrthancResource(boost::make_shared<LoadedDicomResources>(Orthanc::DICOM_TAG_SOP_INSTANCE_UID), 0, source, Orthanc::ResourceType_Instance, instanceId, @@ -108,13 +107,13 @@ } private: - ILoadersContext& context_; + OrthancStone::StoneApplication::Context& context_; boost::shared_ptr<IViewport> viewport_; boost::shared_ptr<DicomResourcesLoader> dicomLoader_; boost::shared_ptr<SeriesFramesLoader> framesLoader_; OrthancStone::Units units_; - SdlSimpleViewerApplication(ILoadersContext& context, + SdlSimpleViewerApplication(OrthancStone::StoneApplication::Context& context, boost::shared_ptr<IViewport> viewport) : context_(context), viewport_(viewport), @@ -173,11 +172,11 @@ //message.GetResources()->GetResource(0).Print(stdout); { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); + SeriesFramesLoader::Factory f(*message.GetResources()); - framesLoader_ = boost::dynamic_pointer_cast<SeriesFramesLoader>( - f.Create(*lock)); + framesLoader_ = boost::dynamic_pointer_cast<SeriesFramesLoader>(f.Create(context_)); Register<SeriesFramesLoader::FrameLoadedMessage>( *framesLoader_, &SdlSimpleViewerApplication::Handle);
--- a/Applications/Samples/WebAssembly/SingleFrameViewer/SingleFrameViewer.cpp Tue Sep 29 17:52:35 2026 +0200 +++ b/Applications/Samples/WebAssembly/SingleFrameViewer/SingleFrameViewer.cpp Wed Sep 30 11:50:48 2026 +0200 @@ -71,8 +71,7 @@ { } -static std::unique_ptr<OrthancStone::WebAssemblyLoadersContext> context_; -static boost::shared_ptr<OrthancStone::Application> application_; +static boost::shared_ptr<OrthancStone::SingleFrameViewerApplication> application_; extern "C" { @@ -97,7 +96,6 @@ configuration.SetDicomCacheSize(128 * 1024 * 1024); // 128MB OrthancStone::StoneApplication::Initialize(configuration); - context_.reset(new OrthancStone::WebAssemblyLoadersContext(1, 4, 1)); DISPATCH_JAVASCRIPT_EVENT("WasmModuleInitialized"); } @@ -111,12 +109,6 @@ { try { - if (context_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls, - "The loaders context is not available yet"); - } - if (application_.get() != NULL) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls, @@ -125,7 +117,7 @@ boost::shared_ptr<OrthancStone::WebGLViewport> viewport( OrthancStone::WebGLViewportsRegistry::GetGlobalRegistry().Add(canvasId)); - application_ = OrthancStone::Application::Create(*context_, viewport); + application_ = OrthancStone::SingleFrameViewerApplication::Create(OrthancStone::StoneApplication::GetInstance(), viewport); { OrthancStone::WebGLViewportsRegistry::Accessor accessor(
--- a/Applications/Samples/WebAssembly/SingleFrameViewer/SingleFrameViewerApplication.h Tue Sep 29 17:52:35 2026 +0200 +++ b/Applications/Samples/WebAssembly/SingleFrameViewer/SingleFrameViewerApplication.h Wed Sep 30 11:50:48 2026 +0200 @@ -35,16 +35,16 @@ namespace OrthancStone { - class Application : public ObserverBase<Application> + class SingleFrameViewerApplication : public ObserverBase<SingleFrameViewerApplication> { private: - ILoadersContext& context_; + StoneApplication::Context& context_; boost::shared_ptr<IViewport> viewport_; boost::shared_ptr<DicomResourcesLoader> dicomLoader_; boost::shared_ptr<SeriesFramesLoader> framesLoader_; - Application(ILoadersContext& context, - boost::shared_ptr<IViewport> viewport) : + SingleFrameViewerApplication(StoneApplication::Context& context, + boost::shared_ptr<IViewport> viewport) : context_(context), viewport_(viewport) { @@ -78,11 +78,11 @@ //message.GetResources()->GetResource(0).Print(stdout); { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); SeriesFramesLoader::Factory f(*message.GetResources()); - framesLoader_ = boost::dynamic_pointer_cast<SeriesFramesLoader>(f.Create(*lock)); - Register<SeriesFramesLoader::FrameLoadedMessage>(*framesLoader_, &Application::Handle); + framesLoader_ = boost::dynamic_pointer_cast<SeriesFramesLoader>(f.Create(context_)); + Register<SeriesFramesLoader::FrameLoadedMessage>(*framesLoader_, &SingleFrameViewerApplication::Handle); assert(message.HasUserPayload()); const Orthanc::SingleValueObject<unsigned int>& payload = @@ -97,17 +97,14 @@ } public: - static boost::shared_ptr<Application> Create(ILoadersContext& context, - boost::shared_ptr<IViewport> viewport) + static boost::shared_ptr<SingleFrameViewerApplication> Create(StoneApplication::Context& context, + boost::shared_ptr<IViewport> viewport) { - boost::shared_ptr<Application> application(new Application(context, viewport)); + boost::shared_ptr<SingleFrameViewerApplication> application(new SingleFrameViewerApplication(context, viewport)); - { - std::unique_ptr<ILoadersContext::ILock> lock(context.Lock()); - application->dicomLoader_ = DicomResourcesLoader::Create(*lock); - } + application->dicomLoader_ = DicomResourcesLoader::Create(context); - application->Register<DicomResourcesLoader::SuccessMessage>(*application->dicomLoader_, &Application::Handle); + application->Register<DicomResourcesLoader::SuccessMessage>(*application->dicomLoader_, &SingleFrameViewerApplication::Handle); return application; } @@ -116,7 +113,7 @@ const std::string& instanceId, unsigned int frame) { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); dicomLoader_->ScheduleLoadOrthancResource( boost::make_shared<LoadedDicomResources>(Orthanc::DICOM_TAG_SOP_INSTANCE_UID), @@ -130,7 +127,7 @@ const std::string& sopInstanceUid, unsigned int frame) { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); // We first must load the "/metadata" to know the number of frames dicomLoader_->ScheduleGetDicomWeb( @@ -176,7 +173,7 @@ Type_DicomWeb = 2 }; - ILoadersContext& context_; + StoneApplication::Context& context_; std::unique_ptr<IWebViewerLoadersObserver> observer_; bool loadThumbnails_; DicomSource source_; @@ -188,7 +185,7 @@ boost::shared_ptr<DicomResourcesLoader> resourcesLoader_; boost::shared_ptr<SeriesThumbnailsLoader> thumbnailsLoader_; - WebViewerLoaders(ILoadersContext& context, + WebViewerLoaders(StoneApplication::Context& context, IWebViewerLoadersObserver* observer) : context_(context), observer_(observer), @@ -303,7 +300,7 @@ } public: - static boost::shared_ptr<WebViewerLoaders> Create(ILoadersContext& context, + static boost::shared_ptr<WebViewerLoaders> Create(StoneApplication::Context& context, const DicomSource& source, bool loadThumbnails, IWebViewerLoadersObserver* observer) @@ -312,35 +309,31 @@ application->source_ = source; application->loadThumbnails_ = loadThumbnails; - { - std::unique_ptr<ILoadersContext::ILock> lock(context.Lock()); - - application->resourcesLoader_ = DicomResourcesLoader::Create(*lock); + application->resourcesLoader_ = DicomResourcesLoader::Create(context); - { - SeriesThumbnailsLoader::Factory f; - f.SetPriority(PRIORITY_THUMBNAILS); - application->thumbnailsLoader_ = boost::dynamic_pointer_cast<SeriesThumbnailsLoader>(f.Create(*lock)); - } + { + SeriesThumbnailsLoader::Factory f; + f.SetPriority(PRIORITY_THUMBNAILS); + application->thumbnailsLoader_ = boost::dynamic_pointer_cast<SeriesThumbnailsLoader>(f.Create(context)); + } - application->Register<OrthancRestApiCommand::SuccessMessage>( - lock->GetOracleObservable(), &WebViewerLoaders::HandleOrthancRestApi); - - application->Register<DicomResourcesLoader::SuccessMessage>( - *application->resourcesLoader_, &WebViewerLoaders::HandleLoadedResources); + application->Register<OrthancRestApiCommand::SuccessMessage>( + context.GetOracleObservable(), &WebViewerLoaders::HandleOrthancRestApi); - application->Register<SeriesThumbnailsLoader::SuccessMessage>( - *application->thumbnailsLoader_, &WebViewerLoaders::HandleThumbnail); + application->Register<DicomResourcesLoader::SuccessMessage>( + *application->resourcesLoader_, &WebViewerLoaders::HandleLoadedResources); - lock->AddLoader(application); - } + application->Register<SeriesThumbnailsLoader::SuccessMessage>( + *application->thumbnailsLoader_, &WebViewerLoaders::HandleThumbnail); + + context.AddLoader(application); return application; } void AddDicomAllSeries() { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); if (source_.IsDicomWeb()) { @@ -354,7 +347,7 @@ std::unique_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand); command->SetMethod(Orthanc::HttpMethod_Get); command->SetUri("/series"); - lock->Schedule(GetSharedObserver(), PRIORITY_ADD_RESOURCES, command.release()); + context_.Schedule(GetSharedObserver(), PRIORITY_ADD_RESOURCES, command.release()); } else { @@ -375,7 +368,7 @@ filter.SetValue(Orthanc::DICOM_TAG_STUDY_INSTANCE_UID, studyInstanceUid, false); { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); std::set<Orthanc::DicomTag> tags; @@ -398,10 +391,7 @@ body["Query"]["StudyInstanceUID"] = studyInstanceUid; command->SetBody(body); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), PRIORITY_ADD_RESOURCES, command.release()); - } + context_.Schedule(GetSharedObserver(), PRIORITY_ADD_RESOURCES, command.release()); } else { @@ -415,7 +405,7 @@ { std::set<Orthanc::DicomTag> tags; - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); if (scheduledStudies_.find(studyInstanceUid) == scheduledStudies_.end()) { @@ -457,7 +447,7 @@ body["Query"]["SeriesInstanceUID"] = seriesInstanceUid; command->SetBody(body); - lock->Schedule(GetSharedObserver(), PRIORITY_ADD_RESOURCES, command.release()); + context_.Schedule(GetSharedObserver(), PRIORITY_ADD_RESOURCES, command.release()); } else { @@ -470,7 +460,7 @@ { if (source_.IsOrthanc()) { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); resourcesLoader_->ScheduleLoadOrthancResources( loadedSeries_, PRIORITY_ADD_RESOURCES, source_, Orthanc::ResourceType_Study, orthancId, Orthanc::ResourceType_Series, @@ -487,7 +477,7 @@ { if (source_.IsOrthanc()) { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); + std::unique_ptr<OrthancStone::IEnvironment::ILock> lock(context_.GetEnvironment().AcquireLock()); resourcesLoader_->ScheduleLoadOrthancResource( loadedSeries_, PRIORITY_ADD_RESOURCES, source_, Orthanc::ResourceType_Series, orthancId,
--- a/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Tue Sep 29 17:52:35 2026 +0200 +++ b/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Wed Sep 30 11:50:48 2026 +0200 @@ -751,7 +751,7 @@ }; private: - OrthancStone::ILoadersContext& context_; + OrthancStone::StoneApplication::Context& context_; std::unique_ptr<IObserver> observer_; OrthancStone::DicomSource source_; size_t pending_; @@ -768,7 +768,7 @@ typedef std::map<std::string, boost::shared_ptr<OrthancStone::DicomStructuredReport> > StructuredReports; StructuredReports structuredReports_; - explicit ResourcesLoader(OrthancStone::ILoadersContext& context, + explicit ResourcesLoader(OrthancStone::StoneApplication::Context& context, const OrthancStone::DicomSource& source) : context_(context), source_(source), @@ -908,8 +908,7 @@ message.GetInstance(i).LookupStringValue(sopClassUid, Orthanc::DICOM_TAG_SOP_CLASS_UID, false) && OrthancStone::IsStructuredReport(OrthancStone::StringToSopClassUid(sopClassUid))) { - std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule( + context_.Schedule( GetSharedObserver(), PRIORITY_NORMAL, OrthancStone::ParseDicomFromWadoCommand::Create( source_, message.GetStudyInstanceUid(), message.GetSeriesInstanceUid(), sopInstanceUid, false /* no transcoding */, Orthanc::DicomTransferSyntax_LittleEndianExplicit /* dummy value */, @@ -1106,12 +1105,9 @@ const std::string uri = ("studies/" + studyInstanceUid + "/series/" + seriesInstanceUid + "/instances/" + sopInstanceUid + "/frames/1/rendered"); - { - std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule( - GetSharedObserver(), PRIORITY_LOW + 2, source_.CreateDicomWebCommand( - uri, arguments, headers, new Orthanc::SingleValueObject<std::string>(virtualSeriesId))); - } + context_.Schedule( + GetSharedObserver(), PRIORITY_LOW + 2, source_.CreateDicomWebCommand( + uri, arguments, headers, new Orthanc::SingleValueObject<std::string>(virtualSeriesId))); } } @@ -1132,14 +1128,14 @@ skipSeriesFromModalities_ = skipSeriesFromModalities; } - static boost::shared_ptr<ResourcesLoader> Create(const OrthancStone::ILoadersContext::ILock& lock, + static boost::shared_ptr<ResourcesLoader> Create(OrthancStone::StoneApplication::Context& context, const OrthancStone::DicomSource& source) { - boost::shared_ptr<ResourcesLoader> loader(new ResourcesLoader(lock.GetContext(), source)); - - loader->resourcesLoader_ = OrthancStone::DicomResourcesLoader::Create(lock); - loader->thumbnailsLoader_ = OrthancStone::SeriesThumbnailsLoader::Create(lock, PRIORITY_LOW); - loader->metadataLoader_ = OrthancStone::SeriesMetadataLoader::Create(lock); + boost::shared_ptr<ResourcesLoader> loader(new ResourcesLoader(context, source)); + + loader->resourcesLoader_ = OrthancStone::DicomResourcesLoader::Create(context); + loader->thumbnailsLoader_ = OrthancStone::SeriesThumbnailsLoader::Create(context, PRIORITY_LOW); + loader->metadataLoader_ = OrthancStone::SeriesMetadataLoader::Create(context); loader->Register<OrthancStone::DicomResourcesLoader::SuccessMessage>( *loader->resourcesLoader_, &ResourcesLoader::Handle); @@ -1151,10 +1147,10 @@ *loader->metadataLoader_, &ResourcesLoader::Handle); loader->Register<OrthancStone::ParseDicomSuccessMessage>( - lock.GetOracleObservable(), &ResourcesLoader::Handle); + context.GetOracleObservable(), &ResourcesLoader::Handle); loader->Register<OrthancStone::HttpCommand::SuccessMessage>( - lock.GetOracleObservable(), &ResourcesLoader::HandleInstanceThumbnail); + context.GetOracleObservable(), &ResourcesLoader::HandleInstanceThumbnail); return loader; } @@ -1447,8 +1443,7 @@ accessor.GetInstance(i).LookupStringValue(sopInstanceUid, Orthanc::DICOM_TAG_SOP_INSTANCE_UID, false) && OrthancStone::StringToSopClassUid(sopClassUid) == OrthancStone::SopClassUid_EncapsulatedPdf) { - std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule( + context_.Schedule( GetSharedObserver(), PRIORITY_NORMAL, OrthancStone::ParseDicomFromWadoCommand::Create( source_, studyInstanceUid, seriesInstanceUid, sopInstanceUid, false /* no transcoding */, Orthanc::DicomTransferSyntax_LittleEndianExplicit /* dummy value */, @@ -2672,7 +2667,7 @@ std::unique_ptr<IObserver> observer_; - OrthancStone::WebAssemblyLoadersContext& context_; + OrthancStone::StoneApplication::Context& context_; boost::shared_ptr<OrthancStone::WebAssemblyViewport> viewport_; boost::shared_ptr<OrthancStone::DicomResourcesLoader> loader_; OrthancStone::DicomSource source_; @@ -3114,8 +3109,7 @@ { if (frames_.get() != NULL) { - std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule( + context_.Schedule( GetSharedObserver(), priority, OrthancStone::ParseDicomFromWadoCommand::Create( source_, studyInstanceUid, seriesInstanceUid, sopInstanceUid, serverSideTranscoding_, Orthanc::DicomTransferSyntax_LittleEndianExplicit, @@ -3157,7 +3151,7 @@ * use the cached DICOM file. **/ std::unique_ptr<OrthancStone::ParsedDicomCache::Accessor> accessor( - context_.GetCachedDicomInstance(instance.GetSopInstanceUid())); + dynamic_cast<OrthancStone::WebAssemblyOracle&>(context_.GetOracle()).GetCachedDicomInstance(instance.GetSopInstanceUid())); if (accessor.get() != NULL && accessor->IsValid()) @@ -3210,10 +3204,7 @@ GetSharedObserver(), instance.GetSopInstanceUid(), frameNumber, windowingTracker_.GetWindowing(), isMonochrome1, isPrefetch))); - { - std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); } } @@ -3235,7 +3226,7 @@ } } - ViewerViewport(OrthancStone::WebAssemblyLoadersContext& context, + ViewerViewport(OrthancStone::StoneApplication::Context& context, const OrthancStone::DicomSource& source, const std::string& canvas, boost::shared_ptr<FramesCache> cache, @@ -3441,7 +3432,7 @@ emscripten_set_wheel_callback(viewport_->GetCanvasCssSelector().c_str(), this, true, NULL); } - static boost::shared_ptr<ViewerViewport> Create(OrthancStone::WebAssemblyLoadersContext& context, + static boost::shared_ptr<ViewerViewport> Create(OrthancStone::StoneApplication::Context& context, const OrthancStone::DicomSource& source, const std::string& canvas, boost::shared_ptr<FramesCache> framesCache, @@ -3453,17 +3444,15 @@ new ViewerViewport(context, source, canvas, framesCache, instancesCache, softwareRendering, linearInterpolation)); { - std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context.Lock()); - - viewport->loader_ = OrthancStone::DicomResourcesLoader::Create(*lock); + viewport->loader_ = OrthancStone::DicomResourcesLoader::Create(context); viewport->Register<OrthancStone::DicomResourcesLoader::SuccessMessage>( *viewport->loader_, &ViewerViewport::Handle); viewport->Register<OrthancStone::HttpCommand::SuccessMessage>( - lock->GetOracleObservable(), &ViewerViewport::Handle); + context.GetOracleObservable(), &ViewerViewport::Handle); viewport->Register<OrthancStone::ParseDicomSuccessMessage>( - lock->GetOracleObservable(), &ViewerViewport::Handle); + context.GetOracleObservable(), &ViewerViewport::Handle); viewport->Register<OrthancStone::AnnotationsSceneLayer::AnnotationChangedMessage>( *viewport->stoneAnnotations_, &ViewerViewport::Handle); @@ -4745,8 +4734,7 @@ if (!resourcesLoader_) { - std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(context_->Lock()); - resourcesLoader_ = ResourcesLoader::Create(*lock, source_); + resourcesLoader_ = ResourcesLoader::Create(OrthancStone::StoneApplication::GetInstance(), source_); resourcesLoader_->AcquireObserver(new WebAssemblyObserver); } @@ -4769,7 +4757,8 @@ if (found == allViewports_.end()) { boost::shared_ptr<ViewerViewport> viewport( - ViewerViewport::Create(*context_, source_, canvas, framesCache_, instancesCache_, softwareRendering_, linearInterpolation_)); + ViewerViewport::Create(OrthancStone::StoneApplication::GetInstance(), + source_, canvas, framesCache_, instancesCache_, softwareRendering_, linearInterpolation_)); viewport->SetMouseButtonActions(leftButtonAction_, middleButtonAction_, rightButtonAction_); viewport->AcquireObserver(new WebAssemblyObserver); viewport->AddLayerSource(*overlayLayerSource_);
--- a/OrthancStone/Sources/Loaders/DicomResourcesLoader.cpp Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/DicomResourcesLoader.cpp Wed Sep 30 11:50:48 2026 +0200 @@ -571,10 +571,7 @@ command->AcquirePayload(new OrthancInstanceTagsHandler(shared_from_this(), target, priority, source, remainingCommands, userPayload)); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); } @@ -591,10 +588,7 @@ command->AcquirePayload(new OrthancOneChildInstanceHandler(shared_from_this(), target, priority, source, remainingCommands, userPayload)); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); } @@ -612,9 +606,9 @@ } - boost::shared_ptr<DicomResourcesLoader> DicomResourcesLoader::Create(const ILoadersContext::ILock& stone) + boost::shared_ptr<DicomResourcesLoader> DicomResourcesLoader::Create(StoneApplication::Context& stone) { - boost::shared_ptr<DicomResourcesLoader> result(new DicomResourcesLoader(stone.GetContext())); + boost::shared_ptr<DicomResourcesLoader> result(new DicomResourcesLoader(stone)); result->Register<HttpCommand::SuccessMessage>(stone.GetOracleObservable(), &DicomResourcesLoader::Handle); result->Register<OracleCommandExceptionMessage>(stone.GetOracleObservable(), &DicomResourcesLoader::Handle); result->Register<OrthancRestApiCommand::SuccessMessage>(stone.GetOracleObservable(), &DicomResourcesLoader::Handle); @@ -679,10 +673,7 @@ source.CreateDicomWebCommand(uri, arguments, headers, new DicomWebHandler(shared_from_this(), target, priority, source, protection))); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); } @@ -742,11 +733,7 @@ source.CreateDicomWebCommand(uri, arguments, headers, new DicomWebHandler(shared_from_this(), target, priority, source, protection))); - - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); } @@ -818,14 +805,10 @@ (shared_from_this(), target, priority, source, remainingCommands, bottomLevel, protection)); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - - // GetSharedObserver() means "this" (for use as an IObserver), as a - // shared_ptr - // The oracle will thus call "this" - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + // GetSharedObserver() means "this" (for use as an IObserver), as a + // shared_ptr + // The oracle will thus call "this" + context_.Schedule(GetSharedObserver(), priority, command.release()); } } @@ -853,10 +836,7 @@ std::unique_ptr<ReadFileCommand> command(new ReadFileCommand(path)); command->AcquirePayload(new DicomDirHandler(shared_from_this(), target, priority, source, protection)); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); #else throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "DCMTK is disabled, cannot load DICOMDIR"); @@ -878,10 +858,7 @@ command->SetPixelDataIncluded(includePixelData); command->AcquirePayload(new Handler(shared_from_this(), target, priority, source, protection)); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); #else throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "DCMTK is disabled, cannot load DICOM files");
--- a/OrthancStone/Sources/Loaders/DicomResourcesLoader.h Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/DicomResourcesLoader.h Wed Sep 30 11:50:48 2026 +0200 @@ -95,12 +95,12 @@ boost::shared_ptr<unsigned int> remainingCommands, boost::shared_ptr<Orthanc::IDynamicObject> userPayload); - explicit DicomResourcesLoader(ILoadersContext& context) : + explicit DicomResourcesLoader(StoneApplication::Context& context) : context_(context) { } - ILoadersContext& context_; + StoneApplication::Context& context_; public: @@ -155,14 +155,14 @@ class Factory : public ILoaderFactory { public: - virtual boost::shared_ptr<IObserver> Create(ILoadersContext::ILock& stone) ORTHANC_OVERRIDE + virtual boost::shared_ptr<IObserver> Create(StoneApplication::Context& stone) ORTHANC_OVERRIDE { return DicomResourcesLoader::Create(stone); } }; - static boost::shared_ptr<DicomResourcesLoader> Create(const ILoadersContext::ILock& stone); + static boost::shared_ptr<DicomResourcesLoader> Create(StoneApplication::Context& stone); void ScheduleGetDicomWeb(boost::shared_ptr<LoadedDicomResources> target, int priority,
--- a/OrthancStone/Sources/Loaders/DicomVolumeLoader.cpp Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/DicomVolumeLoader.cpp Wed Sep 30 11:50:48 2026 +0200 @@ -152,7 +152,7 @@ } - boost::shared_ptr<IObserver> DicomVolumeLoader::Factory::Create(ILoadersContext::ILock& context) + boost::shared_ptr<IObserver> DicomVolumeLoader::Factory::Create(StoneApplication::Context& context) { boost::shared_ptr<SeriesFramesLoader> frames = boost::dynamic_pointer_cast<SeriesFramesLoader>(framesFactory_.Create(context));
--- a/OrthancStone/Sources/Loaders/DicomVolumeLoader.h Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/DicomVolumeLoader.h Wed Sep 30 11:50:48 2026 +0200 @@ -114,7 +114,7 @@ framesFactory_.SetDicomDir(dicomDirPath, dicomDir); } - virtual boost::shared_ptr<IObserver> Create(ILoadersContext::ILock& context) ORTHANC_OVERRIDE; + virtual boost::shared_ptr<IObserver> Create(StoneApplication::Context& context) ORTHANC_OVERRIDE; }; bool IsValid() const
--- a/OrthancStone/Sources/Loaders/ILoaderFactory.h Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/ILoaderFactory.h Wed Sep 30 11:50:48 2026 +0200 @@ -23,6 +23,7 @@ #pragma once +#include "../StoneApplication.h" #include "ILoadersContext.h" namespace OrthancStone @@ -38,6 +39,6 @@ * Factory function that creates a new loader, to be used by the * Stone loaders context. **/ - virtual boost::shared_ptr<IObserver> Create(ILoadersContext::ILock& context) = 0; + virtual boost::shared_ptr<IObserver> Create(StoneApplication::Context& context) = 0; }; }
--- a/OrthancStone/Sources/Loaders/SeriesFramesLoader.cpp Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/SeriesFramesLoader.cpp Wed Sep 30 11:50:48 2026 +0200 @@ -115,7 +115,7 @@ }; - SeriesFramesLoader::SeriesFramesLoader(ILoadersContext& context, + SeriesFramesLoader::SeriesFramesLoader(StoneApplication::Context& context, LoadedDicomResources& instances, const std::string& dicomDirPath, boost::shared_ptr<LoadedDicomResources> dicomDir) : @@ -312,10 +312,10 @@ } - boost::shared_ptr<IObserver> SeriesFramesLoader::Factory::Create(ILoadersContext::ILock& stone) + boost::shared_ptr<IObserver> SeriesFramesLoader::Factory::Create(StoneApplication::Context& stone) { boost::shared_ptr<SeriesFramesLoader> loader( - new SeriesFramesLoader(stone.GetContext(), instances_, dicomDirPath_, dicomDir_)); + new SeriesFramesLoader(stone, instances_, dicomDirPath_, dicomDir_)); loader->Register<GetOrthancImageCommand::SuccessMessage>(stone.GetOracleObservable(), &SeriesFramesLoader::Handle); loader->Register<GetOrthancWebViewerJpegCommand::SuccessMessage>(stone.GetOracleObservable(), &SeriesFramesLoader::Handle); loader->Register<HttpCommand::SuccessMessage>(stone.GetOracleObservable(), &SeriesFramesLoader::Handle); @@ -371,10 +371,7 @@ command->SetPixelDataIncluded(true); command->AcquirePayload(new Payload(source, index, sopInstanceUid, quality, protection.release())); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); } else { @@ -410,11 +407,8 @@ std::unique_ptr<Payload> payload(new Payload(source, index, sopInstanceUid, quality, protection.release())); payload->SetWindowing(windowing); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, - source.CreateDicomWebCommand(uri + "/rendered", arguments, headers, payload.release())); - } + context_.Schedule(GetSharedObserver(), priority, + source.CreateDicomWebCommand(uri + "/rendered", arguments, headers, payload.release())); } else { @@ -432,10 +426,7 @@ source.CreateDicomWebCommand(uri, empty, empty, NULL))); command->AcquirePayload(payload.release()); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); #else throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented, "DCMTK is not enabled, cannot parse a DICOM instance"); @@ -469,10 +460,7 @@ command->SetExpectedPixelFormat(parameters.GetExpectedPixelFormat()); command->AcquirePayload(new Payload(source, index, sopInstanceUid, quality, protection.release())); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); } else if (quality == 0 && source.HasOrthancAdvancedPreview()) { @@ -491,10 +479,7 @@ command->SetHttpHeader("Accept", Orthanc::MIME_PAM); command->AcquirePayload(new Payload(source, index, sopInstanceUid, quality, protection.release())); - { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority, command.release()); - } + context_.Schedule(GetSharedObserver(), priority, command.release()); } } else
--- a/OrthancStone/Sources/Loaders/SeriesFramesLoader.h Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/SeriesFramesLoader.h Wed Sep 30 11:50:48 2026 +0200 @@ -43,12 +43,12 @@ private: class Payload; - ILoadersContext& context_; + StoneApplication::Context& context_; SeriesOrderedFrames frames_; std::string dicomDirPath_; boost::shared_ptr<LoadedDicomResources> dicomDir_; - SeriesFramesLoader(ILoadersContext& context, + SeriesFramesLoader(StoneApplication::Context& context, LoadedDicomResources& instances, const std::string& dicomDirPath, boost::shared_ptr<LoadedDicomResources> dicomDir); @@ -159,7 +159,7 @@ void SetDicomDir(const std::string& dicomDirPath, boost::shared_ptr<LoadedDicomResources> dicomDir); - virtual boost::shared_ptr<IObserver> Create(ILoadersContext::ILock& context) ORTHANC_OVERRIDE; + virtual boost::shared_ptr<IObserver> Create(StoneApplication::Context& context) ORTHANC_OVERRIDE; }; const SeriesOrderedFrames& GetOrderedFrames() const
--- a/OrthancStone/Sources/Loaders/SeriesMetadataLoader.cpp Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/SeriesMetadataLoader.cpp Wed Sep 30 11:50:48 2026 +0200 @@ -189,7 +189,7 @@ } - boost::shared_ptr<SeriesMetadataLoader> SeriesMetadataLoader::Create(const ILoadersContext::ILock& context) + boost::shared_ptr<SeriesMetadataLoader> SeriesMetadataLoader::Create(StoneApplication::Context& context) { boost::shared_ptr<DicomResourcesLoader> loader(DicomResourcesLoader::Create(context));
--- a/OrthancStone/Sources/Loaders/SeriesMetadataLoader.h Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/SeriesMetadataLoader.h Wed Sep 30 11:50:48 2026 +0200 @@ -130,14 +130,14 @@ class Factory : public ILoaderFactory { public: - virtual boost::shared_ptr<IObserver> Create(ILoadersContext::ILock& context) ORTHANC_OVERRIDE + virtual boost::shared_ptr<IObserver> Create(StoneApplication::Context& context) ORTHANC_OVERRIDE { return SeriesMetadataLoader::Create(context); } }; - static boost::shared_ptr<SeriesMetadataLoader> Create(const ILoadersContext::ILock& context); + static boost::shared_ptr<SeriesMetadataLoader> Create(StoneApplication::Context& context); class Accessor : public boost::noncopyable
--- a/OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.cpp Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.cpp Wed Sep 30 11:50:48 2026 +0200 @@ -457,8 +457,7 @@ void SeriesThumbnailsLoader::Schedule(IOracleCommand* command) { - std::unique_ptr<ILoadersContext::ILock> lock(context_.Lock()); - lock->Schedule(GetSharedObserver(), priority_, command); + context_.Schedule(GetSharedObserver(), priority_, command); } @@ -586,7 +585,7 @@ } - SeriesThumbnailsLoader::SeriesThumbnailsLoader(ILoadersContext& context, + SeriesThumbnailsLoader::SeriesThumbnailsLoader(StoneApplication::Context& context, int priority) : context_(context), priority_(priority), @@ -596,11 +595,10 @@ } - boost::shared_ptr<SeriesThumbnailsLoader> SeriesThumbnailsLoader::Create( - const ILoadersContext::ILock& stone, - int priority) + boost::shared_ptr<SeriesThumbnailsLoader> SeriesThumbnailsLoader::Create(StoneApplication::Context& stone, + int priority) { - boost::shared_ptr<SeriesThumbnailsLoader> result(new SeriesThumbnailsLoader(stone.GetContext(), priority)); + boost::shared_ptr<SeriesThumbnailsLoader> result(new SeriesThumbnailsLoader(stone, priority)); result->Register<GetOrthancImageCommand::SuccessMessage>(stone.GetOracleObservable(), &SeriesThumbnailsLoader::Handle); result->Register<HttpCommand::SuccessMessage>(stone.GetOracleObservable(), &SeriesThumbnailsLoader::Handle); result->Register<OracleCommandExceptionMessage>(stone.GetOracleObservable(), &SeriesThumbnailsLoader::Handle);
--- a/OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.h Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/Loaders/SeriesThumbnailsLoader.h Wed Sep 30 11:50:48 2026 +0200 @@ -148,7 +148,7 @@ // Maps a "Series Instance UID" to a thumbnail typedef std::map<std::string, Thumbnail*> Thumbnails; - ILoadersContext& context_; + StoneApplication::Context& context_; Thumbnails thumbnails_; int priority_; unsigned int width_; @@ -174,7 +174,7 @@ void Handle(const OracleCommandExceptionMessage& message); - SeriesThumbnailsLoader(ILoadersContext& context, + SeriesThumbnailsLoader(StoneApplication::Context& context, int priority); public: @@ -194,7 +194,7 @@ priority_ = priority; } - virtual boost::shared_ptr<IObserver> Create(ILoadersContext::ILock& context) + virtual boost::shared_ptr<IObserver> Create(StoneApplication::Context& context) { return SeriesThumbnailsLoader::Create(context, priority_); } @@ -207,7 +207,7 @@ } - static boost::shared_ptr<SeriesThumbnailsLoader> Create(const ILoadersContext::ILock& context, + static boost::shared_ptr<SeriesThumbnailsLoader> Create(StoneApplication::Context& context, int priority); void SetThumbnailSize(unsigned int width,
--- a/OrthancStone/Sources/StoneApplication.cpp Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/StoneApplication.cpp Wed Sep 30 11:50:48 2026 +0200 @@ -23,6 +23,7 @@ #include "StoneApplication.h" +#include "Loaders/OracleScheduler.h" #include "StoneException.h" #include <Compatibility.h> @@ -273,6 +274,8 @@ #else # error Support your platform here #endif + + oracleScheduler_ = OracleScheduler::Create(*this, 1, 4, 1); // TODO Refactoring - Parameters } @@ -312,6 +315,26 @@ } + void StoneApplication::Context::Schedule(boost::shared_ptr<IObserver> receiver, + int priority, + IOracleCommand* command /* Takes ownership */) + { + assert(oracleScheduler_); + + { + std::unique_ptr<IEnvironment::ILock> lock(GetEnvironment().AcquireLock()); + oracleScheduler_->Schedule(receiver, priority, command); + } + } + + + void StoneApplication::Context::AddLoader(const boost::shared_ptr<IObserver>& loader) + { + Orthanc::Mutex::ScopedLock lock(loadersMutex_); + loaders_.push_back(loader); + } + + bool StoneApplication::Run() { try
--- a/OrthancStone/Sources/StoneApplication.h Tue Sep 29 17:52:35 2026 +0200 +++ b/OrthancStone/Sources/StoneApplication.h Wed Sep 30 11:50:48 2026 +0200 @@ -31,9 +31,14 @@ #include <WebServiceParameters.h> +#include <MultiThreading/Mutex.h> // TODO Refactoring - Remove this +#include <list> // TODO Refactoring - Remove this + namespace OrthancStone { + class OracleScheduler; + class StoneApplication : public boost::noncopyable { public: @@ -113,6 +118,11 @@ class PImpl; PImpl* pimpl_; + boost::shared_ptr<OracleScheduler> oracleScheduler_; + + Orthanc::Mutex loadersMutex_; // TODO Refactoring - Remove this + std::list< boost::shared_ptr<IObserver> > loaders_; // TODO Refactoring - Remove this + public: Context(const Configuration& configuration); @@ -126,6 +136,21 @@ const IMessage& message) ORTHANC_OVERRIDE; IObservable& GetOracleObservable(); // TODO Refactoring - Remove this + + void Schedule(boost::shared_ptr<IObserver> receiver, + int priority, + IOracleCommand* command /* Takes ownership */); // TODO Refactoring - Remove this + + /** + * Add a reference to the given observer in the Stone loaders + * context. This can be used to match the lifetime of a loader + * with the lifetime of the Stone context: This is useful if + * your Stone application does not keep a reference to the + * loader by itself (typically in global promises), which would + * make the loader disappear as soon as the scope of the + * variable is left. + **/ + void AddLoader(const boost::shared_ptr<IObserver>& loader); // TODO Refactoring - Remove this };
