Mercurial > hg > orthanc-stone
view OrthancStone/Sources/StoneApplication.cpp @ 2390:ba477e5a4981 refactoring tip
class PeriodicRunnableThread moved to orthanc
| author | Sebastien Jodogne <s.jodogne@gmail.com> |
|---|---|
| date | Wed, 21 Oct 2026 14:53:38 +0200 |
| parents | d63042924e59 |
| children |
line wrap: on
line source
/** * Stone of Orthanc * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * Copyright (C) 2017-2023 Osimis S.A., Belgium * Copyright (C) 2021-2026 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/>. **/ #include "StoneApplication.h" #include "Loaders/OracleScheduler.h" #include "StoneException.h" #include <Compatibility.h> #include <Logging.h> #include <MultiThreading/Mutex.h> #if ORTHANC_STONE_TARGET_PLATFORM_WASM == 1 # include "Platforms/WebAssembly/WebAssemblyEnvironment.h" # include "Platforms/WebAssembly/WebAssemblyOracle.h" #elif ORTHANC_STONE_TARGET_PLATFORM_NATIVE == 1 # include "Platforms/Native/NativeEnvironment.h" # include "Platforms/Native/ThreadedOracle.h" #else # error Support your platform here #endif namespace OrthancStone { StoneApplication::Configuration::Configuration() : isLocalOrthanc_(false), rootDirectory_("."), oracleThreadsCount_(4), workersTimeResolution_(50), // By default, time resolution of 50ms dicomCacheSize_(0) // By default, the cache is disabled { } void StoneApplication::Configuration::SetRemoteOrthancParameters(const Orthanc::WebServiceParameters& orthanc) { isLocalOrthanc_ = false; remoteOrthanc_ = orthanc; } const Orthanc::WebServiceParameters& StoneApplication::Configuration::GetRemoteOrthancParameters() const { if (isLocalOrthanc_) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } else { return remoteOrthanc_; } } void StoneApplication::Configuration::SetLocalOrthancRoot(const std::string& root) { isLocalOrthanc_ = true; localOrthancRoot_ = root; } const std::string& StoneApplication::Configuration::GetLocalOrthancRoot() const { if (isLocalOrthanc_) { return localOrthancRoot_; } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } } void StoneApplication::Configuration::SetOracleThreadsCount(unsigned int count) { if (count == 0) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } else { oracleThreadsCount_ = count; } } void StoneApplication::Configuration::SetWorkersTimeResolution(unsigned int milliseconds) { if (milliseconds == 0) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } else { workersTimeResolution_ = milliseconds; } } #if ORTHANC_STONE_TARGET_PLATFORM_WASM == 1 class StoneApplication::Context::PImpl { private: class Emitter : public IMessageEmitter // TODO Refactoring - Remove this { private: IObservable oracleObservable_; public: void EmitMessage(boost::weak_ptr<IObserver> observer, const IMessage& message) ORTHANC_OVERRIDE { oracleObservable_.EmitMessage(observer, message); } IObservable& GetOracleObservable() { return oracleObservable_; } }; WebAssemblyEnvironment environment_; WebAssemblyOracle oracle_; Emitter emitter_; public: PImpl(const Configuration& configuration) : oracle_(configuration) { } IEnvironment& GetEnvironment() { return environment_; } WebAssemblyOracle& GetOracle() { return oracle_; } IMessageEmitter& GetMessageEmitter() { return emitter_; } IObservable& GetOracleObservable() { return emitter_.GetOracleObservable(); } void Start() { } void Stop() { } }; #endif #if ORTHANC_STONE_TARGET_PLATFORM_NATIVE == 1 class StoneApplication::Context::PImpl { private: class Emitter : public IMessageEmitter // TODO Refactoring - Remove this { private: NativeEnvironment& environment_; IObservable oracleObservable_; public: Emitter(NativeEnvironment& environment) : environment_(environment) { } void EmitMessage(boost::weak_ptr<IObserver> observer, const IMessage& message) ORTHANC_OVERRIDE { NativeEnvironment::Lock lock(environment_); if (lock.IsFirstLock()) // For debugging { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } oracleObservable_.EmitMessage(observer, message); } IObservable& GetOracleObservable() { return oracleObservable_; } }; NativeEnvironment environment_; ThreadedOracle oracle_; Emitter emitter_; public: PImpl(const Configuration& configuration) : environment_(configuration.GetWorkersTimeResolution()), oracle_(configuration), emitter_(environment_) { } IEnvironment& GetEnvironment() { return environment_; } ThreadedOracle& GetOracle() { return oracle_; } IMessageEmitter& GetMessageEmitter() { return emitter_; } IObservable& GetOracleObservable() { return emitter_.GetOracleObservable(); } void Start() { environment_.Start(); oracle_.Start(); } void Stop() { oracle_.Stop(); environment_.Stop(); } }; #endif StoneApplication::Context::Context(const Configuration& configuration) { #if ORTHANC_STONE_TARGET_PLATFORM_WASM == 1 pimpl_ = new PImpl(configuration); #elif ORTHANC_STONE_TARGET_PLATFORM_NATIVE == 1 pimpl_ = new PImpl(configuration); #else # error Support your platform here #endif oracleScheduler_ = OracleScheduler::Create(*this, 1, 4, 1); // TODO Refactoring - Parameters } StoneApplication::Context::~Context() { assert(pimpl_ != NULL); delete pimpl_; } IEnvironment& StoneApplication::Context::GetEnvironment() { assert(pimpl_ != NULL); return pimpl_->GetEnvironment(); } IOracle& StoneApplication::Context::GetOracle() { assert(pimpl_ != NULL); return pimpl_->GetOracle(); } void StoneApplication::Context::EmitMessage(boost::weak_ptr<IObserver> observer, const IMessage& message) { assert(pimpl_ != NULL); return pimpl_->GetMessageEmitter().EmitMessage(observer, message); } IObservable& StoneApplication::Context::GetOracleObservable() { assert(pimpl_ != NULL); return pimpl_->GetOracleObservable(); } 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); } void StoneApplication::Start() { if (context_) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } else { context_.reset(new Context(configuration_)); assert(context_.get() != NULL); assert(context_->pimpl_ != NULL); context_->pimpl_->Start(); } } const boost::shared_ptr<StoneApplication::Context>& StoneApplication::GetContext() { if (context_) { return context_; } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } } void StoneApplication::Stop() { if (context_) { context_->pimpl_->Stop(); } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } } static Orthanc::Mutex applicationMutex_; // TODO Refactoring - Remove this static std::unique_ptr<StoneApplication::Context> application_; // TODO Refactoring - Remove this StoneApplication::Context& StoneApplication::GetInstance() { Orthanc::Mutex::ScopedLock lock(applicationMutex_); if (application_.get() == NULL) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } return *application_; } void StoneApplication::Initialize(const Configuration& configuration) { Orthanc::Mutex::ScopedLock lock(applicationMutex_); if (application_.get() == NULL) { application_.reset(new StoneApplication::Context(configuration)); application_->pimpl_->Start(); } else { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } } void StoneApplication::Finalize() { Orthanc::Mutex::ScopedLock lock(applicationMutex_); if (application_.get() != NULL) { application_->pimpl_->Stop(); application_.reset(NULL); } } }
