# HG changeset patch # User Sebastien Jodogne # Date 1559041376 -7200 # Node ID bc20e4c417ecd0a58b0cc04f102ea5d01f658cab # Parent 04f518ebd1327b2a77a75ce7e3ba4d08c9e33520 refactoring OrthancMultiframeVolumeLoader using LoaderStateMachine diff -r 04f518ebd132 -r bc20e4c417ec Samples/Sdl/Loader.cpp --- a/Samples/Sdl/Loader.cpp Tue May 28 12:26:16 2019 +0200 +++ b/Samples/Sdl/Loader.cpp Tue May 28 13:02:56 2019 +0200 @@ -989,10 +989,21 @@ { } - void Schedule(OracleCommandWithPayload* command) + State(const State& currentState) : + that_(currentState.that_) + { + } + + void Schedule(OracleCommandWithPayload* command) const { that_.Schedule(command); } + + template + T& GetLoader() const + { + return dynamic_cast(that_); + } virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const { @@ -1013,6 +1024,11 @@ void Schedule(OracleCommandWithPayload* command) { std::auto_ptr protection(command); + + if (command == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } if (!command->HasPayload()) { @@ -1021,6 +1037,7 @@ } pendingCommands_.push_back(protection.release()); + Step(); } void Start() @@ -1030,6 +1047,8 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } + active_ = true; + for (size_t i = 0; i < simultaneousDownloads_; i++) { Step(); @@ -1039,28 +1058,36 @@ private: void Step() { - if (!pendingCommands_.empty()) + if (!pendingCommands_.empty() && + activeCommands_ < simultaneousDownloads_) { oracle_.Schedule(*this, pendingCommands_.front()); pendingCommands_.pop_front(); + + activeCommands_++; } } - - void Handle(const OrthancRestApiCommand::SuccessMessage& message) - { - dynamic_cast(message.GetOrigin().GetPayload()).Handle(message); - Step(); - } - void Handle(const GetOrthancImageCommand::SuccessMessage& message) + void Clear() + { + for (PendingCommands::iterator it = pendingCommands_.begin(); + it != pendingCommands_.end(); ++it) + { + delete *it; + } + } + + void HandleException(const OracleCommandExceptionMessage& message) + { + LOG(ERROR) << "Error in the state machine, stopping all processing"; + Clear(); + } + + template + void Handle(const T& message) { dynamic_cast(message.GetOrigin().GetPayload()).Handle(message); - Step(); - } - - void Handle(const GetOrthancWebViewerJpegCommand::SuccessMessage& message) - { - dynamic_cast(message.GetOrigin().GetPayload()).Handle(message); + activeCommands_--; Step(); } @@ -1070,6 +1097,7 @@ bool active_; unsigned int simultaneousDownloads_; PendingCommands pendingCommands_; + unsigned int activeCommands_; public: LoaderStateMachine(IOracle& oracle, @@ -1077,31 +1105,37 @@ IObserver(oracleObservable.GetBroker()), oracle_(oracle), active_(false), - simultaneousDownloads_(4) + simultaneousDownloads_(4), + activeCommands_(0) { oracleObservable.RegisterObserverCallback( new Callable - (*this, &LoaderStateMachine::Handle)); + (*this, &LoaderStateMachine::Handle)); oracleObservable.RegisterObserverCallback( new Callable - (*this, &LoaderStateMachine::Handle)); + (*this, &LoaderStateMachine::Handle)); oracleObservable.RegisterObserverCallback( new Callable - (*this, &LoaderStateMachine::Handle)); + (*this, &LoaderStateMachine::Handle)); + + oracleObservable.RegisterObserverCallback( + new Callable + (*this, &LoaderStateMachine::HandleException)); } virtual ~LoaderStateMachine() { - for (PendingCommands::iterator it = pendingCommands_.begin(); - it != pendingCommands_.end(); ++it) - { - delete *it; - } + Clear(); } - virtual void SetSimultaneousDownloads(unsigned int count) + bool IsActive() const + { + return active_; + } + + void SetSimultaneousDownloads(unsigned int count) { if (active_) { @@ -1121,41 +1155,10 @@ class OrthancMultiframeVolumeLoader : - public IObserver, + public LoaderStateMachine, public IObservable { private: - class State : public Orthanc::IDynamicObject - { - private: - OrthancMultiframeVolumeLoader& that_; - - protected: - void Schedule(OrthancRestApiCommand* command) const - { - that_.oracle_.Schedule(that_, command); - } - - OrthancMultiframeVolumeLoader& GetTarget() const - { - return that_; - } - - public: - State(OrthancMultiframeVolumeLoader& that) : - that_(that) - { - } - - virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const = 0; - }; - - void Handle(const OrthancRestApiCommand::SuccessMessage& message) - { - dynamic_cast(message.GetOrigin().GetPayload()).Handle(message); - } - - class LoadRTDoseGeometry : public State { private: @@ -1171,6 +1174,7 @@ { throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); } + } virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const @@ -1179,7 +1183,7 @@ std::string s = Orthanc::Toolbox::StripSpaces(message.GetAnswer()); dicom_->SetValue(Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR, s, false); - GetTarget().SetGeometry(*dicom_); + GetLoader().SetGeometry(*dicom_); } }; @@ -1209,6 +1213,8 @@ virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const { + OrthancMultiframeVolumeLoader& loader = GetLoader(); + Json::Value body; message.ParseJsonBody(body); @@ -1226,15 +1232,15 @@ // mandatory for RT-DOSE, but is too long to be returned by default std::auto_ptr command(new OrthancRestApiCommand); - command->SetUri("/instances/" + GetTarget().GetInstanceId() + "/content/" + + command->SetUri("/instances/" + loader.GetInstanceId() + "/content/" + Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR.Format()); - command->SetPayload(new LoadRTDoseGeometry(GetTarget(), dicom.release())); + command->SetPayload(new LoadRTDoseGeometry(loader, dicom.release())); Schedule(command.release()); } else { - GetTarget().SetGeometry(*dicom); + loader.SetGeometry(*dicom); } } }; @@ -1251,7 +1257,7 @@ virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const { - GetTarget().SetTransferSyntax(message.GetAnswer()); + GetLoader().SetTransferSyntax(message.GetAnswer()); } }; @@ -1266,22 +1272,20 @@ virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const { - GetTarget().SetUncompressedPixelData(message.GetAnswer()); + GetLoader().SetUncompressedPixelData(message.GetAnswer()); } }; boost::shared_ptr volume_; - IOracle& oracle_; - bool active_; std::string instanceId_; std::string transferSyntaxUid_; const std::string& GetInstanceId() const { - if (active_) + if (IsActive()) { return instanceId_; } @@ -1309,7 +1313,7 @@ command->SetUri("/instances/" + instanceId_ + "/content/" + Orthanc::DICOM_TAG_PIXEL_DATA.Format() + "/0"); command->SetPayload(new LoadUncompressedPixelData(*this)); - oracle_.Schedule(*this, command.release()); + Schedule(command.release()); } else { @@ -1451,48 +1455,36 @@ OrthancMultiframeVolumeLoader(const boost::shared_ptr& volume, IOracle& oracle, IObservable& oracleObservable) : - IObserver(oracleObservable.GetBroker()), + LoaderStateMachine(oracle, oracleObservable), IObservable(oracleObservable.GetBroker()), - volume_(volume), - oracle_(oracle), - active_(false) + volume_(volume) { if (volume.get() == NULL) { throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); } - - oracleObservable.RegisterObserverCallback( - new Callable - (*this, &OrthancMultiframeVolumeLoader::Handle)); } void LoadInstance(const std::string& instanceId) { - if (active_) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - active_ = true; - instanceId_ = instanceId; + Start(); + + instanceId_ = instanceId; - { - std::auto_ptr command(new OrthancRestApiCommand); - command->SetHttpHeader("Accept-Encoding", "gzip"); - command->SetUri("/instances/" + instanceId + "/tags"); - command->SetPayload(new LoadGeometry(*this)); - oracle_.Schedule(*this, command.release()); - } + { + std::auto_ptr command(new OrthancRestApiCommand); + command->SetHttpHeader("Accept-Encoding", "gzip"); + command->SetUri("/instances/" + instanceId + "/tags"); + command->SetPayload(new LoadGeometry(*this)); + Schedule(command.release()); + } - { - std::auto_ptr command(new OrthancRestApiCommand); - command->SetUri("/instances/" + instanceId + "/metadata/TransferSyntax"); - command->SetPayload(new LoadTransferSyntax(*this)); - oracle_.Schedule(*this, command.release()); - } + { + std::auto_ptr command(new OrthancRestApiCommand); + command->SetUri("/instances/" + instanceId + "/metadata/TransferSyntax"); + command->SetPayload(new LoadTransferSyntax(*this)); + Schedule(command.release()); } } }; @@ -2028,8 +2020,8 @@ printf("Geometry ready\n"); //plane_ = message.GetOrigin().GetGeometry().GetSagittalGeometry(); - plane_ = message.GetOrigin().GetGeometry().GetAxialGeometry(); - //plane_ = message.GetOrigin().GetGeometry().GetCoronalGeometry(); + //plane_ = message.GetOrigin().GetGeometry().GetAxialGeometry(); + plane_ = message.GetOrigin().GetGeometry().GetCoronalGeometry(); plane_.SetOrigin(message.GetOrigin().GetGeometry().GetCoordinates(0.5f, 0.5f, 0.5f)); Refresh(); @@ -2286,7 +2278,7 @@ // 2017-11-17-Anonymized //ctLoader->LoadSeries("cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT doseLoader->LoadInstance("41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE - rtstructLoader->LoadInstance("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT + //rtstructLoader->LoadInstance("83d9c0c3-913a7fee-610097d7-cbf0522d-fd75bee6"); // RT-STRUCT // 2015-01-28-Multiframe //doseLoader->LoadInstance("88f71e2a-5fad1c61-96ed14d6-5b3d3cf7-a5825279"); // Multiframe CT