changeset 271:46c5296d867e am-2

OracleWebService and BasicSdlApplicationContext using the same global mutex
author am@osimis.io
date Thu, 23 Aug 2018 17:12:54 +0200
parents 2d64f4d39610
children d7d91d96b9d8
files Applications/BasicApplicationContext.h Applications/Samples/SimpleViewerApplication.h Applications/Sdl/BasicSdlApplication.cpp Applications/Sdl/BasicSdlApplicationContext.cpp Applications/Sdl/BasicSdlApplicationContext.h Applications/Sdl/SdlEngine.cpp Applications/Sdl/SdlEngine.h Framework/Toolbox/OrthancApiClient.cpp Framework/Toolbox/OrthancApiClient.h Framework/Widgets/LayerWidget.cpp Framework/Widgets/LayerWidget.h Platforms/Generic/Oracle.cpp Platforms/Generic/Oracle.h Platforms/Generic/OracleWebService.h Platforms/Generic/WebServiceCommandBase.cpp Platforms/Generic/WebServiceCommandBase.h Platforms/Generic/WebServiceGetCommand.cpp Platforms/Generic/WebServiceGetCommand.h Platforms/Generic/WebServicePostCommand.cpp Platforms/Generic/WebServicePostCommand.h
diffstat 20 files changed, 191 insertions(+), 207 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/BasicApplicationContext.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Applications/BasicApplicationContext.h	Thu Aug 23 17:12:54 2018 +0200
@@ -21,7 +21,7 @@
 
 #pragma once
 
-#include "../Platforms/Generic/OracleWebService.h"
+#include "../Framework/Toolbox/IWebService.h"
 #include "../Framework/Viewport/WidgetViewport.h"
 
 #include <list>
@@ -32,14 +32,18 @@
   {
 
   protected:
-    IWebService& webService_;
+    IWebService* webService_;
   public:
-    BasicApplicationContext(IWebService& webService)
-      : webService_(webService)
+    BasicApplicationContext()
+      : webService_(NULL)
     {
     }
 
-    virtual IWebService& GetWebService() {return webService_;}
+    IWebService& GetWebService() {return *webService_;}
+    void SetWebService(IWebService& webService)
+    {
+      webService_ = &webService;
+    }
 //    virtual IWidget& SetCentralWidget(IWidget* widget) = 0;   // Takes ownership
 
     virtual ~BasicApplicationContext() {}
--- a/Applications/Samples/SimpleViewerApplication.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Applications/Samples/SimpleViewerApplication.h	Thu Aug 23 17:12:54 2018 +0200
@@ -162,8 +162,6 @@
       {
         boost::program_options::options_description generic("Sample options");
         generic.add_options()
-            //          ("study", boost::program_options::value<std::string>(),
-            //           "Orthanc ID of the study")
             ("studyId", boost::program_options::value<std::string>(),
              "Orthanc ID of the study")
             ;
@@ -193,7 +191,7 @@
           thumbnailsLayout_->SetBackgroundColor(50, 50, 50);
           thumbnailsLayout_->SetVertical();
 
-          mainViewport_ = new LayerWidget(broker_);
+          mainViewport_ = new LayerWidget(broker_, "main-viewport");
           mainViewport_->RegisterObserver(*this);
 
           // hierarchy
@@ -204,10 +202,6 @@
           smartLoader_.reset(new SmartLoader(broker_, context_->GetWebService()));
           smartLoader_->SetImageQuality(SliceImageQuality_FullPam);
 
-//          mainViewport_->AddLayer(smartLoader_->GetFrame(instances_[currentInstanceIndex_], 0));
-//          thumbnails_[0]->AddLayer(smartLoader_->GetFrame(instances_[0], 0));
-//          thumbnails_[1]->AddLayer(smartLoader_->GetFrame(instances_[1], 0));
-
           mainLayout_->SetTransmitMouseOver(true);
           interactor_.reset(new Interactor(*this));
           mainViewport_->SetInteractor(*interactor_);
@@ -253,19 +247,16 @@
         {
           LoadThumbnailForSeries(response["ID"].asString(), response["Instances"][0].asString());
         }
-        //TODO: create layout and start loading frames
-        //mainViewport_->AddLayer(smartLoader_->GetFrame(instances_[currentInstanceIndex_], 0));
-        //thumbnails_[0]->AddLayer(smartLoader_->GetFrame(instances_[0], 0));
-        //thumbnails_[1]->AddLayer(smartLoader_->GetFrame(instances_[1], 0));
       }
 
       void LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId)
       {
-        LayerWidget* thumbnailWidget = new LayerWidget(broker_);
+        LOG(INFO) << "Loading thumbnail for series " << seriesId;
+        LayerWidget* thumbnailWidget = new LayerWidget(broker_, "thumbnail-series-" + seriesId);
+        thumbnails_.push_back(thumbnailWidget);
+        thumbnailsLayout_->AddWidget(thumbnailWidget);
         thumbnailWidget->RegisterObserver(*this);
         thumbnailWidget->AddLayer(smartLoader_->GetFrame(instanceId, 0));
-        thumbnailsLayout_->AddWidget(thumbnailWidget);
-        thumbnails_.push_back(thumbnailWidget);
       }
 
       void SelectStudy(const std::string& studyId)
@@ -273,15 +264,10 @@
         orthancApiClient_->ScheduleGetStudy(*this, studyId);
       }
 
-      void LoadSeries(const std::vector<std::string>& seriesIds)
-      {
-//        instances_.push_back(parameters["studyId"].as<std::string>());
-//        instances_.push_back(parameters["instance2"].as<std::string>());
-      }
-
       virtual void HandleMessage(IObservable& from, const IMessage& message) {
         switch (message.GetType()) {
         case MessageType_Widget_GeometryChanged:
+          LOG(INFO) << "Widget geometry ready: " << dynamic_cast<LayerWidget&>(from).GetName();
           dynamic_cast<LayerWidget&>(from).SetDefaultView();
           break;
         case MessageType_OrthancApi_GetStudyIds_Ready:
--- a/Applications/Sdl/BasicSdlApplication.cpp	Thu Aug 23 14:45:04 2018 +0200
+++ b/Applications/Sdl/BasicSdlApplication.cpp	Thu Aug 23 17:12:54 2018 +0200
@@ -33,6 +33,7 @@
 #include <Core/HttpClient.h>
 #include <Core/Toolbox.h>
 #include <Plugins/Samples/Common/OrthancHttpConnection.h>
+#include "../../Platforms/Generic/OracleWebService.h"
 
 namespace OrthancStone
 {
@@ -224,17 +225,17 @@
 
       LogStatusBar statusBar;
 
-      boost::mutex stoneGlobalMutex;
-      Oracle oracle(stoneGlobalMutex, 4); // use 4 threads to download content
-      OracleWebService webService(broker, oracle, webServiceParameters);
-      BasicSdlApplicationContext context(webService);
+      BasicSdlApplicationContext context;
+      Oracle oracle(4); // use 4 threads to download content
+      OracleWebService webService(broker, oracle, webServiceParameters, context);
+      context.SetWebService(webService);
 
       application.Initialize(&context, statusBar, parameters);
 
       {
-        BasicSdlApplicationContext::ViewportLocker locker(context);
+        BasicSdlApplicationContext::GlobalMutexLocker locker(context);
         context.SetCentralWidget(application.GetCentralWidget());
-        locker.GetViewport().SetStatusBar(statusBar);
+        context.GetCentralViewport().SetStatusBar(statusBar);
       }
 
       std::string title = application.GetTitle();
@@ -254,8 +255,8 @@
         SdlEngine sdl(window, context);
 
         {
-          BasicSdlApplicationContext::ViewportLocker locker(context);
-          locker.GetViewport().Register(sdl);  // (*)
+          BasicSdlApplicationContext::GlobalMutexLocker locker(context);
+          context.GetCentralViewport().Register(sdl);  // (*)
         }
 
         context.Start();
--- a/Applications/Sdl/BasicSdlApplicationContext.cpp	Thu Aug 23 14:45:04 2018 +0200
+++ b/Applications/Sdl/BasicSdlApplicationContext.cpp	Thu Aug 23 17:12:54 2018 +0200
@@ -20,6 +20,7 @@
 
 
 #include "BasicSdlApplicationContext.h"
+#include "../../Platforms/Generic/OracleWebService.h"
 
 namespace OrthancStone
 {
@@ -35,8 +36,8 @@
     while (!that->stopped_)
     {
       {
-        ViewportLocker locker(*that);
-        locker.GetViewport().UpdateContent();
+        GlobalMutexLocker locker(*that);
+        that->GetCentralViewport().UpdateContent();
       }
       
       boost::this_thread::sleep(boost::posix_time::milliseconds(that->updateDelay_));
@@ -44,12 +45,7 @@
   }
   
 
-  BasicSdlApplicationContext::BasicSdlApplicationContext(OracleWebService& webService) : // Orthanc::WebServiceParameters& orthanc, WidgetViewport* centralViewport) :
-    BasicApplicationContext(webService),
-    oracleWebService_(&webService),
-//    oracle_(viewportMutex_, 4),  // Use 4 threads to download
-//    webService_(oracle_, orthanc),
-//    centralViewport_(centralViewport),
+  BasicSdlApplicationContext::BasicSdlApplicationContext() : // Orthanc::WebServiceParameters& orthanc, WidgetViewport* centralViewport) :
     centralViewport_(new OrthancStone::WidgetViewport()),
     stopped_(true),
     updateDelay_(100)   // By default, 100ms between each refresh of the content
@@ -60,7 +56,7 @@
 
   void BasicSdlApplicationContext::Start()
   {
-    oracleWebService_->Start();
+    dynamic_cast<OracleWebService*>(webService_)->Start();
 
     if (centralViewport_->HasUpdateContent())
     {
@@ -79,6 +75,6 @@
       updateThread_.join();
     }
     
-    oracleWebService_->Stop();
+    dynamic_cast<OracleWebService*>(webService_)->Stop();
   }
 }
--- a/Applications/Sdl/BasicSdlApplicationContext.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Applications/Sdl/BasicSdlApplicationContext.h	Thu Aug 23 17:12:54 2018 +0200
@@ -25,7 +25,6 @@
 #include "../../Framework/Volumes/ISlicedVolume.h"
 #include "../../Framework/Volumes/IVolumeLoader.h"
 #include "../../Framework/Widgets/IWorldSceneInteractor.h"
-#include "../../Platforms/Generic/OracleWebService.h"
 
 #include <list>
 #include <boost/thread.hpp>
@@ -39,45 +38,49 @@
 
     static void UpdateThread(BasicSdlApplicationContext* that);
 
-    OracleWebService*   oracleWebService_;
-    boost::mutex        viewportMutex_;
+    boost::mutex        globalMutex_;
     std::unique_ptr<WidgetViewport>      centralViewport_;
     boost::thread       updateThread_;
     bool                stopped_;
     unsigned int        updateDelay_;
 
   public:
-    class ViewportLocker : public boost::noncopyable
+    class GlobalMutexLocker: public boost::noncopyable
     {
-    private:
       boost::mutex::scoped_lock  lock_;
-      IViewport&                 viewport_;
-
     public:
-      ViewportLocker(BasicSdlApplicationContext& that) :
-        lock_(that.viewportMutex_),
-        viewport_(*(that.centralViewport_.get()))
-      {
-      }
-
-      IViewport& GetViewport() const
-      {
-        return viewport_;
-      }
+      GlobalMutexLocker(BasicSdlApplicationContext& that):
+        lock_(that.globalMutex_)
+      {}
     };
 
+//    class ViewportLocker : public boost::noncopyable
+//    {
+//    private:
+//      boost::mutex::scoped_lock  lock_;
+//      IViewport&                 viewport_;
+
+//    public:
+//      ViewportLocker(BasicSdlApplicationContext& that) :
+//        lock_(that.viewportMutex_),
+//        viewport_(*(that.centralViewport_.get()))
+//      {
+//      }
+
+//      IViewport& GetViewport() const
+//      {
+//        return viewport_;
+//      }
+//    };
+
     
-    BasicSdlApplicationContext(OracleWebService& webService);
+    BasicSdlApplicationContext();
 
     virtual ~BasicSdlApplicationContext() {}
 
     virtual IWidget& SetCentralWidget(IWidget* widget);   // Takes ownership
+    IViewport& GetCentralViewport() {return *(centralViewport_.get());}
 
-    virtual IWebService& GetWebService()
-    {
-      return webService_;
-    }
-    
     void Start();
 
     void Stop();
--- a/Applications/Sdl/SdlEngine.cpp	Thu Aug 23 14:45:04 2018 +0200
+++ b/Applications/Sdl/SdlEngine.cpp	Thu Aug 23 17:12:54 2018 +0200
@@ -29,11 +29,10 @@
 
 namespace OrthancStone
 {
-  void SdlEngine::SetSize(BasicSdlApplicationContext::ViewportLocker& locker,
-                          unsigned int width,
+  void SdlEngine::SetSize(unsigned int width,
                           unsigned int height)
   {
-    locker.GetViewport().SetSize(width, height);
+    context_.GetCentralViewport().SetSize(width, height);
     surface_.SetSize(width, height);
   }
     
@@ -42,8 +41,8 @@
   {
     if (viewportChanged_)
     {
-      BasicSdlApplicationContext::ViewportLocker locker(context_);
-      surface_.Render(locker.GetViewport());
+      BasicSdlApplicationContext::GlobalMutexLocker locker(context_);
+      surface_.Render(context_.GetCentralViewport());
 
       viewportChanged_ = false;
     }
@@ -119,9 +118,9 @@
     const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount);
 
     {
-      BasicSdlApplicationContext::ViewportLocker locker(context_);
-      SetSize(locker, window_.GetWidth(), window_.GetHeight());
-      locker.GetViewport().SetDefaultView();
+      BasicSdlApplicationContext::GlobalMutexLocker locker(context_);
+      SetSize(window_.GetWidth(), window_.GetHeight());
+      context_.GetCentralViewport().SetDefaultView();
     }
     
     bool stop = false;
@@ -134,7 +133,7 @@
       while (!stop &&
              SDL_PollEvent(&event))
       {
-        BasicSdlApplicationContext::ViewportLocker locker(context_);
+        BasicSdlApplicationContext::GlobalMutexLocker locker(context_);
 
         if (event.type == SDL_QUIT) 
         {
@@ -148,15 +147,15 @@
           switch (event.button.button)
           {
             case SDL_BUTTON_LEFT:
-              locker.GetViewport().MouseDown(MouseButton_Left, event.button.x, event.button.y, modifiers);
+              context_.GetCentralViewport().MouseDown(MouseButton_Left, event.button.x, event.button.y, modifiers);
               break;
             
             case SDL_BUTTON_RIGHT:
-              locker.GetViewport().MouseDown(MouseButton_Right, event.button.x, event.button.y, modifiers);
+              context_.GetCentralViewport().MouseDown(MouseButton_Right, event.button.x, event.button.y, modifiers);
               break;
             
             case SDL_BUTTON_MIDDLE:
-              locker.GetViewport().MouseDown(MouseButton_Middle, event.button.x, event.button.y, modifiers);
+              context_.GetCentralViewport().MouseDown(MouseButton_Middle, event.button.x, event.button.y, modifiers);
               break;
 
             default:
@@ -165,26 +164,26 @@
         }
         else if (event.type == SDL_MOUSEMOTION)
         {
-          locker.GetViewport().MouseMove(event.button.x, event.button.y);
+          context_.GetCentralViewport().MouseMove(event.button.x, event.button.y);
         }
         else if (event.type == SDL_MOUSEBUTTONUP)
         {
-          locker.GetViewport().MouseUp();
+          context_.GetCentralViewport().MouseUp();
         }
         else if (event.type == SDL_WINDOWEVENT)
         {
           switch (event.window.event)
           {
             case SDL_WINDOWEVENT_LEAVE:
-              locker.GetViewport().MouseLeave();
+              context_.GetCentralViewport().MouseLeave();
               break;
 
             case SDL_WINDOWEVENT_ENTER:
-              locker.GetViewport().MouseEnter();
+              context_.GetCentralViewport().MouseEnter();
               break;
 
             case SDL_WINDOWEVENT_SIZE_CHANGED:
-              SetSize(locker, event.window.data1, event.window.data2);
+              SetSize(event.window.data1, event.window.data2);
               break;
 
             default:
@@ -200,11 +199,11 @@
 
           if (event.wheel.y > 0)
           {
-            locker.GetViewport().MouseWheel(MouseWheelDirection_Up, x, y, modifiers);
+            context_.GetCentralViewport().MouseWheel(MouseWheelDirection_Up, x, y, modifiers);
           }
           else if (event.wheel.y < 0)
           {
-            locker.GetViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers);
+            context_.GetCentralViewport().MouseWheel(MouseWheelDirection_Down, x, y, modifiers);
           }
         }
         else if (event.type == SDL_KEYDOWN &&
@@ -214,50 +213,50 @@
 
           switch (event.key.keysym.sym)
           {
-            case SDLK_a:    locker.GetViewport().KeyPressed('a', modifiers);  break;
-            case SDLK_b:    locker.GetViewport().KeyPressed('b', modifiers);  break;
-            case SDLK_c:    locker.GetViewport().KeyPressed('c', modifiers);  break;
-            case SDLK_d:    locker.GetViewport().KeyPressed('d', modifiers);  break;
-            case SDLK_e:    locker.GetViewport().KeyPressed('e', modifiers);  break;
+            case SDLK_a:    context_.GetCentralViewport().KeyPressed('a', modifiers);  break;
+            case SDLK_b:    context_.GetCentralViewport().KeyPressed('b', modifiers);  break;
+            case SDLK_c:    context_.GetCentralViewport().KeyPressed('c', modifiers);  break;
+            case SDLK_d:    context_.GetCentralViewport().KeyPressed('d', modifiers);  break;
+            case SDLK_e:    context_.GetCentralViewport().KeyPressed('e', modifiers);  break;
             case SDLK_f:    window_.ToggleMaximize();                         break;
-            case SDLK_g:    locker.GetViewport().KeyPressed('g', modifiers);  break;
-            case SDLK_h:    locker.GetViewport().KeyPressed('h', modifiers);  break;
-            case SDLK_i:    locker.GetViewport().KeyPressed('i', modifiers);  break;
-            case SDLK_j:    locker.GetViewport().KeyPressed('j', modifiers);  break;
-            case SDLK_k:    locker.GetViewport().KeyPressed('k', modifiers);  break;
-            case SDLK_l:    locker.GetViewport().KeyPressed('l', modifiers);  break;
-            case SDLK_m:    locker.GetViewport().KeyPressed('m', modifiers);  break;
-            case SDLK_n:    locker.GetViewport().KeyPressed('n', modifiers);  break;
-            case SDLK_o:    locker.GetViewport().KeyPressed('o', modifiers);  break;
-            case SDLK_p:    locker.GetViewport().KeyPressed('p', modifiers);  break;
+            case SDLK_g:    context_.GetCentralViewport().KeyPressed('g', modifiers);  break;
+            case SDLK_h:    context_.GetCentralViewport().KeyPressed('h', modifiers);  break;
+            case SDLK_i:    context_.GetCentralViewport().KeyPressed('i', modifiers);  break;
+            case SDLK_j:    context_.GetCentralViewport().KeyPressed('j', modifiers);  break;
+            case SDLK_k:    context_.GetCentralViewport().KeyPressed('k', modifiers);  break;
+            case SDLK_l:    context_.GetCentralViewport().KeyPressed('l', modifiers);  break;
+            case SDLK_m:    context_.GetCentralViewport().KeyPressed('m', modifiers);  break;
+            case SDLK_n:    context_.GetCentralViewport().KeyPressed('n', modifiers);  break;
+            case SDLK_o:    context_.GetCentralViewport().KeyPressed('o', modifiers);  break;
+            case SDLK_p:    context_.GetCentralViewport().KeyPressed('p', modifiers);  break;
             case SDLK_q:    stop = true;                                      break;
-            case SDLK_r:    locker.GetViewport().KeyPressed('r', modifiers);  break;
-            case SDLK_s:    locker.GetViewport().KeyPressed('s', modifiers);  break;
-            case SDLK_t:    locker.GetViewport().KeyPressed('t', modifiers);  break;
-            case SDLK_u:    locker.GetViewport().KeyPressed('u', modifiers);  break;
-            case SDLK_v:    locker.GetViewport().KeyPressed('v', modifiers);  break;
-            case SDLK_w:    locker.GetViewport().KeyPressed('w', modifiers);  break;
-            case SDLK_x:    locker.GetViewport().KeyPressed('x', modifiers);  break;
-            case SDLK_y:    locker.GetViewport().KeyPressed('y', modifiers);  break;
-            case SDLK_z:    locker.GetViewport().KeyPressed('z', modifiers);  break;
-            case SDLK_KP_0: locker.GetViewport().KeyPressed('0', modifiers);  break;
-            case SDLK_KP_1: locker.GetViewport().KeyPressed('1', modifiers);  break;
-            case SDLK_KP_2: locker.GetViewport().KeyPressed('2', modifiers);  break;
-            case SDLK_KP_3: locker.GetViewport().KeyPressed('3', modifiers);  break;
-            case SDLK_KP_4: locker.GetViewport().KeyPressed('4', modifiers);  break;
-            case SDLK_KP_5: locker.GetViewport().KeyPressed('5', modifiers);  break;
-            case SDLK_KP_6: locker.GetViewport().KeyPressed('6', modifiers);  break;
-            case SDLK_KP_7: locker.GetViewport().KeyPressed('7', modifiers);  break;
-            case SDLK_KP_8: locker.GetViewport().KeyPressed('8', modifiers);  break;
-            case SDLK_KP_9: locker.GetViewport().KeyPressed('9', modifiers);  break;
+            case SDLK_r:    context_.GetCentralViewport().KeyPressed('r', modifiers);  break;
+            case SDLK_s:    context_.GetCentralViewport().KeyPressed('s', modifiers);  break;
+            case SDLK_t:    context_.GetCentralViewport().KeyPressed('t', modifiers);  break;
+            case SDLK_u:    context_.GetCentralViewport().KeyPressed('u', modifiers);  break;
+            case SDLK_v:    context_.GetCentralViewport().KeyPressed('v', modifiers);  break;
+            case SDLK_w:    context_.GetCentralViewport().KeyPressed('w', modifiers);  break;
+            case SDLK_x:    context_.GetCentralViewport().KeyPressed('x', modifiers);  break;
+            case SDLK_y:    context_.GetCentralViewport().KeyPressed('y', modifiers);  break;
+            case SDLK_z:    context_.GetCentralViewport().KeyPressed('z', modifiers);  break;
+            case SDLK_KP_0: context_.GetCentralViewport().KeyPressed('0', modifiers);  break;
+            case SDLK_KP_1: context_.GetCentralViewport().KeyPressed('1', modifiers);  break;
+            case SDLK_KP_2: context_.GetCentralViewport().KeyPressed('2', modifiers);  break;
+            case SDLK_KP_3: context_.GetCentralViewport().KeyPressed('3', modifiers);  break;
+            case SDLK_KP_4: context_.GetCentralViewport().KeyPressed('4', modifiers);  break;
+            case SDLK_KP_5: context_.GetCentralViewport().KeyPressed('5', modifiers);  break;
+            case SDLK_KP_6: context_.GetCentralViewport().KeyPressed('6', modifiers);  break;
+            case SDLK_KP_7: context_.GetCentralViewport().KeyPressed('7', modifiers);  break;
+            case SDLK_KP_8: context_.GetCentralViewport().KeyPressed('8', modifiers);  break;
+            case SDLK_KP_9: context_.GetCentralViewport().KeyPressed('9', modifiers);  break;
 
             case SDLK_PLUS:
             case SDLK_KP_PLUS:
-              locker.GetViewport().KeyPressed('+', modifiers);  break;
+              context_.GetCentralViewport().KeyPressed('+', modifiers);  break;
 
             case SDLK_MINUS:
             case SDLK_KP_MINUS:
-              locker.GetViewport().KeyPressed('-', modifiers);  break;
+              context_.GetCentralViewport().KeyPressed('-', modifiers);  break;
 
             default:
               break;
--- a/Applications/Sdl/SdlEngine.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Applications/Sdl/SdlEngine.h	Thu Aug 23 17:12:54 2018 +0200
@@ -36,8 +36,7 @@
     SdlCairoSurface           surface_;
     bool                      viewportChanged_;
 
-    void SetSize(BasicSdlApplicationContext::ViewportLocker& locker,
-                 unsigned int width,
+    void SetSize(unsigned int width,
                  unsigned int height);
     
     void RenderFrame();
--- a/Framework/Toolbox/OrthancApiClient.cpp	Thu Aug 23 14:45:04 2018 +0200
+++ b/Framework/Toolbox/OrthancApiClient.cpp	Thu Aug 23 17:12:54 2018 +0200
@@ -58,7 +58,7 @@
   // Once the response is ready, it will emit a message to the responseObserver
   // the responseObserver must handle only that message (and not all messages from the OrthancApiClient)
   class OrthancApiClient::BaseRequest:
-      public IObserver,
+//      public IObserver,
       public IObservable,
       public Orthanc::IDynamicObject
   {
@@ -75,7 +75,8 @@
                    const std::string& uri,
                    MessageType messageToEmitWhenResponseReady,
                    OrthancApiClient::Mode mode)
-      : IObserver(orthanc.broker_),
+      :
+        //IObserver(orthanc.broker_),
         IObservable(orthanc.broker_),
         uri_(uri),
         orthanc_(orthanc),
@@ -85,30 +86,30 @@
       // this object will emit only a single message, the one the final responseObserver is expecting
       DeclareEmittableMessage(messageToEmitWhenResponseReady);
 
-      // this object is observing the OrthancApi so it must handle all messages
-      DeclareHandledMessage(MessageType_OrthancApi_InternalGetJsonResponseReady);
-      DeclareIgnoredMessage(MessageType_OrthancApi_InternalGetJsonResponseError);
+//      // this object is observing the OrthancApi so it must handle all messages
+//      DeclareHandledMessage(MessageType_OrthancApi_InternalGetJsonResponseReady);
+//      DeclareIgnoredMessage(MessageType_OrthancApi_InternalGetJsonResponseError);
 
-      orthanc_.RegisterObserver(*this);
+      //orthanc_.RegisterObserver(*this);
       this->RegisterObserver(responseObserver);
     }
     virtual ~BaseRequest() {}
 
-    // mainly maps OrthancApi internal messages to a message that is expected by the responseObserver
-    virtual void HandleMessage(IObservable& from, const IMessage& message)
-    {
-      switch (message.GetType())
-      {
-        case MessageType_OrthancApi_InternalGetJsonResponseReady:
-      {
-        const OrthancApiClient::InternalGetJsonResponseReadyMessage& messageReceived = dynamic_cast<const OrthancApiClient::InternalGetJsonResponseReadyMessage&>(message);
-        EmitMessage(OrthancApiClient::GetJsonResponseReadyMessage(messageToEmitWhenResponseReady_, messageReceived.request_->uri_, messageReceived.response_));
-        orthanc_.ReleaseRequest(messageReceived.request_);
-      }; break;
-      default:
-        throw MessageNotDeclaredException(message.GetType());
-      }
-    }
+//    // mainly maps OrthancApi internal messages to a message that is expected by the responseObserver
+//    virtual void HandleMessage(IObservable& from, const IMessage& message)
+//    {
+//      switch (message.GetType())
+//      {
+//        case MessageType_OrthancApi_InternalGetJsonResponseReady:
+//      {
+//        const OrthancApiClient::InternalGetJsonResponseReadyMessage& messageReceived = dynamic_cast<const OrthancApiClient::InternalGetJsonResponseReadyMessage&>(message);
+//        EmitMessage(OrthancApiClient::GetJsonResponseReadyMessage(messageToEmitWhenResponseReady_, messageReceived.request_->uri_, messageReceived.response_));
+//        orthanc_.ReleaseRequest(messageReceived.request_);
+//      }; break;
+//      default:
+//        throw MessageNotDeclaredException(message.GetType());
+//      }
+//    }
 
   };
 
@@ -139,20 +140,19 @@
         Json::Value response;
         if (MessagingToolbox::ParseJson(response, answer, answerSize))
         {
-          OrthancApiClient::InternalGetJsonResponseReadyMessage msg(request, response);
-          that_.EmitMessage(msg);
+          request->EmitMessage(OrthancApiClient::GetJsonResponseReadyMessage(request->messageToEmitWhenResponseReady_, request->uri_, response));
         }
         else
         {
-          OrthancApiClient::InternalGetJsonResponseErrorMessage msg(request);
-          that_.EmitMessage(msg);
+//          OrthancApiClient::InternalGetJsonResponseErrorMessage msg(request);
+//          that_.EmitMessage(msg);
         }
       };  break;
 
       default:
-        that_.ReleaseRequest(request);
         throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
       }
+      that_.ReleaseRequest(request);
     }
 
     virtual void OnHttpRequestError(const std::string& uri,
@@ -164,14 +164,15 @@
       {
       case OrthancApiClient::Mode_GetJson:
       {
-        OrthancApiClient::InternalGetJsonResponseErrorMessage msg(request);
-        that_.EmitMessage(msg);
+//        OrthancApiClient::InternalGetJsonResponseErrorMessage msg(request);
+//        that_.EmitMessage(msg);
+          // TODO: the request shall send an error message
       };  break;
 
       default:
-        that_.ReleaseRequest(request);
         throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
       }
+      that_.ReleaseRequest(request);
     }
   };
 
--- a/Framework/Toolbox/OrthancApiClient.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Framework/Toolbox/OrthancApiClient.h	Thu Aug 23 17:12:54 2018 +0200
@@ -50,8 +50,8 @@
                                   const std::string& uri,
                                   const Json::Value& response)
         : IMessage(messageType),
-          uri_(uri),
-          response_(response)
+          response_(response),
+          uri_(uri)
       {
       }
     };
--- a/Framework/Widgets/LayerWidget.cpp	Thu Aug 23 14:45:04 2018 +0200
+++ b/Framework/Widgets/LayerWidget.cpp	Thu Aug 23 17:12:54 2018 +0200
@@ -359,10 +359,11 @@
   }
 
   
-  LayerWidget::LayerWidget(MessageBroker& broker) :
+  LayerWidget::LayerWidget(MessageBroker& broker, const std::string& name) :
     IObserver(broker),
     IObservable(broker),
-    started_(false)
+    started_(false),
+    name_(name)
   {
     DeclareHandledMessage(MessageType_LayerSource_GeometryReady);
     DeclareHandledMessage(MessageType_LayerSource_ContentChanged);
@@ -523,7 +524,7 @@
     size_t i;
     if (LookupLayer(i, source))
     {
-      LOG(INFO) << "Geometry ready for layer " << i;
+      LOG(INFO) << name_ << ": Geometry ready for layer " << i;
 
       changedLayers_[i] = true;
       //layers_[i]->ScheduleLayerCreation(slice_);
--- a/Framework/Widgets/LayerWidget.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Framework/Widgets/LayerWidget.h	Thu Aug 23 17:12:54 2018 +0200
@@ -48,6 +48,7 @@
     std::auto_ptr<Scene>        currentScene_;
     std::auto_ptr<Scene>        pendingScene_;
     std::vector<bool>           changedLayers_;
+    std::string                 name_;
 
     bool LookupLayer(size_t& index /* out */,
                      const ILayerSource& layer) const;
@@ -71,7 +72,7 @@
     void ResetChangedLayers();
 
   public:
-    LayerWidget(MessageBroker& broker);
+    LayerWidget(MessageBroker& broker, const std::string& name);
 
     virtual void HandleMessage(IObservable& from, const IMessage& message);
 
@@ -92,9 +93,9 @@
     void InvalidateLayer(size_t layer);
     
   public:
-    LayerWidget();
+    virtual ~LayerWidget();
 
-    virtual ~LayerWidget();
+    const std::string& GetName() const {return name_;}
 
     size_t AddLayer(ILayerSource* layer);  // Takes ownership
 
--- a/Platforms/Generic/Oracle.cpp	Thu Aug 23 14:45:04 2018 +0200
+++ b/Platforms/Generic/Oracle.cpp	Thu Aug 23 17:12:54 2018 +0200
@@ -27,6 +27,7 @@
 
 #include <vector>
 #include <stdio.h>
+#include <boost/thread/mutex.hpp>
 
 namespace OrthancStone
 {
@@ -40,7 +41,6 @@
       State_Stopped
     };
 
-    boost::mutex*                  globalMutex_;
     boost::mutex                   oracleMutex_;
     State                          state_;
     std::vector<boost::thread*>    threads_;
@@ -71,23 +71,13 @@
           // Random sleeping to test
           //boost::this_thread::sleep(boost::posix_time::milliseconds(50 * (1 + rand() % 10)));
 
-          if (that->globalMutex_ != NULL)
-          {
-            boost::mutex::scoped_lock lock(*that->globalMutex_);
-            command.Commit();
-          }
-          else
-          {
-            command.Commit();
-          }
+          command.Commit();
         }
       }
     }
     
   public:
-    PImpl(boost::mutex* globalMutex,
-          unsigned int threadCount) :
-      globalMutex_(globalMutex),
+    PImpl(unsigned int threadCount) :
       state_(State_Init),
       threads_(threadCount)
     {
@@ -182,19 +172,11 @@
   };
   
 
-  Oracle::Oracle(boost::mutex& globalMutex,
-                 unsigned int threadCount) :
-    pimpl_(new PImpl(&globalMutex, threadCount))
+  Oracle::Oracle(unsigned int threadCount) :
+    pimpl_(new PImpl(threadCount))
   {
   }
 
-
-  Oracle::Oracle(unsigned int threadCount) :
-    pimpl_(new PImpl(NULL, threadCount))
-  {
-  }
-
-
   void Oracle::Start()
   {
     pimpl_->Start();
--- a/Platforms/Generic/Oracle.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Platforms/Generic/Oracle.h	Thu Aug 23 17:12:54 2018 +0200
@@ -24,7 +24,6 @@
 #include "IOracleCommand.h"
 
 #include <boost/shared_ptr.hpp>
-#include <boost/thread/mutex.hpp>
 
 namespace OrthancStone
 {
@@ -36,9 +35,6 @@
     boost::shared_ptr<PImpl>  pimpl_;
 
   public:
-    Oracle(boost::mutex& globalMutex,
-           unsigned int threadCount);
-
     Oracle(unsigned int threadCount);
 
     void Start();
--- a/Platforms/Generic/OracleWebService.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Platforms/Generic/OracleWebService.h	Thu Aug 23 17:12:54 2018 +0200
@@ -25,6 +25,7 @@
 #include "Oracle.h"
 #include "WebServiceGetCommand.h"
 #include "WebServicePostCommand.h"
+#include "../../Applications/Sdl/BasicSdlApplicationContext.h"
 
 namespace OrthancStone
 {
@@ -32,14 +33,17 @@
   {
   private:
     Oracle&                        oracle_;
+    BasicSdlApplicationContext&    context_;
     Orthanc::WebServiceParameters  parameters_;
 
   public:
     OracleWebService(MessageBroker& broker,
                      Oracle& oracle,
-                     const Orthanc::WebServiceParameters& parameters) : 
+                     const Orthanc::WebServiceParameters& parameters,
+                     BasicSdlApplicationContext& context) :
       IWebService(broker),
       oracle_(oracle),
+      context_(context),
       parameters_(parameters)
     {
     }
@@ -49,7 +53,7 @@
                                     const Headers& headers,
                                     Orthanc::IDynamicObject* payload)
     {
-      oracle_.Submit(new WebServiceGetCommand(broker_, callback, parameters_, uri, headers, payload));
+      oracle_.Submit(new WebServiceGetCommand(broker_, callback, parameters_, uri, headers, payload, context_));
     }
 
     virtual void SchedulePostRequest(ICallback& callback,
@@ -58,7 +62,7 @@
                                      const std::string& body,
                                      Orthanc::IDynamicObject* payload)
     {
-      oracle_.Submit(new WebServicePostCommand(broker_, callback, parameters_, uri, headers, body, payload));
+      oracle_.Submit(new WebServicePostCommand(broker_, callback, parameters_, uri, headers, body, payload, context_));
     }
 
     void Start()
--- a/Platforms/Generic/WebServiceCommandBase.cpp	Thu Aug 23 14:45:04 2018 +0200
+++ b/Platforms/Generic/WebServiceCommandBase.cpp	Thu Aug 23 17:12:54 2018 +0200
@@ -26,17 +26,19 @@
 namespace OrthancStone
 {
   WebServiceCommandBase::WebServiceCommandBase(MessageBroker& broker,
-                                             IWebService::ICallback& callback,
-                                             const Orthanc::WebServiceParameters& parameters,
-                                             const std::string& uri,
-                                             const IWebService::Headers& headers,
-                                             Orthanc::IDynamicObject* payload /* takes ownership */) :
+                                               IWebService::ICallback& callback,
+                                               const Orthanc::WebServiceParameters& parameters,
+                                               const std::string& uri,
+                                               const IWebService::Headers& headers,
+                                               Orthanc::IDynamicObject* payload /* takes ownership */,
+                                               BasicSdlApplicationContext& context) :
     IObservable(broker),
     callback_(callback),
     parameters_(parameters),
     uri_(uri),
     headers_(headers),
-    payload_(payload)
+    payload_(payload),
+    context_(context)
   {
     DeclareEmittableMessage(MessageType_HttpRequestError);
     DeclareEmittableMessage(MessageType_HttpRequestSuccess);
@@ -46,6 +48,8 @@
 
   void WebServiceCommandBase::Commit()
   {
+    BasicSdlApplicationContext::GlobalMutexLocker lock(context_);  // we want to make sure that, i.e, the UpdateThread is not triggered while we are updating the "model" with the result of a WebServiceCommand
+
     if (success_)
     {
       IWebService::ICallback::HttpRequestSuccessMessage message(uri_, answer_.c_str(), answer_.size(), payload_.release());
--- a/Platforms/Generic/WebServiceCommandBase.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Platforms/Generic/WebServiceCommandBase.h	Thu Aug 23 17:12:54 2018 +0200
@@ -25,6 +25,7 @@
 
 #include "../../Framework/Toolbox/IWebService.h"
 #include "../../Framework/Messages/IObservable.h"
+#include "../../Applications/Sdl/BasicSdlApplicationContext.h"
 
 #include <Core/WebServiceParameters.h>
 
@@ -42,14 +43,16 @@
     std::auto_ptr<Orthanc::IDynamicObject>  payload_;
     bool                                    success_;
     std::string                             answer_;
+    BasicSdlApplicationContext&             context_;
 
   public:
     WebServiceCommandBase(MessageBroker& broker,
-                         IWebService::ICallback& callback,
-                         const Orthanc::WebServiceParameters& parameters,
-                         const std::string& uri,
-                         const std::map<std::string, std::string>& headers,
-                         Orthanc::IDynamicObject* payload /* takes ownership */);
+                          IWebService::ICallback& callback,
+                          const Orthanc::WebServiceParameters& parameters,
+                          const std::string& uri,
+                          const std::map<std::string, std::string>& headers,
+                          Orthanc::IDynamicObject* payload /* takes ownership */,
+                          BasicSdlApplicationContext& context);
 
     virtual void Execute() = 0;
 
--- a/Platforms/Generic/WebServiceGetCommand.cpp	Thu Aug 23 14:45:04 2018 +0200
+++ b/Platforms/Generic/WebServiceGetCommand.cpp	Thu Aug 23 17:12:54 2018 +0200
@@ -30,8 +30,9 @@
                                              const Orthanc::WebServiceParameters& parameters,
                                              const std::string& uri,
                                              const IWebService::Headers& headers,
-                                             Orthanc::IDynamicObject* payload /* takes ownership */) :
-    WebServiceCommandBase(broker, callback, parameters, uri, headers, payload)
+                                             Orthanc::IDynamicObject* payload /* takes ownership */,
+                                             BasicSdlApplicationContext& context) :
+    WebServiceCommandBase(broker, callback, parameters, uri, headers, payload, context)
   {
   }
 
--- a/Platforms/Generic/WebServiceGetCommand.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Platforms/Generic/WebServiceGetCommand.h	Thu Aug 23 17:12:54 2018 +0200
@@ -33,7 +33,8 @@
                          const Orthanc::WebServiceParameters& parameters,
                          const std::string& uri,
                          const IWebService::Headers& headers,
-                         Orthanc::IDynamicObject* payload /* takes ownership */);
+                         Orthanc::IDynamicObject* payload /* takes ownership */,
+                         BasicSdlApplicationContext& context);
 
     virtual void Execute();
   };
--- a/Platforms/Generic/WebServicePostCommand.cpp	Thu Aug 23 14:45:04 2018 +0200
+++ b/Platforms/Generic/WebServicePostCommand.cpp	Thu Aug 23 17:12:54 2018 +0200
@@ -31,8 +31,9 @@
                                                const std::string& uri,
                                                const IWebService::Headers& headers,
                                                const std::string& body,
-                                               Orthanc::IDynamicObject* payload /* takes ownership */) :
-    WebServiceCommandBase(broker, callback, parameters, uri, headers, payload),
+                                               Orthanc::IDynamicObject* payload /* takes ownership */,
+                                               BasicSdlApplicationContext& context) :
+    WebServiceCommandBase(broker, callback, parameters, uri, headers, payload, context),
     body_(body)
   {
   }
--- a/Platforms/Generic/WebServicePostCommand.h	Thu Aug 23 14:45:04 2018 +0200
+++ b/Platforms/Generic/WebServicePostCommand.h	Thu Aug 23 17:12:54 2018 +0200
@@ -37,7 +37,8 @@
                           const std::string& uri,
                           const IWebService::Headers& headers,
                           const std::string& body,
-                          Orthanc::IDynamicObject* payload /* takes ownership */);
+                          Orthanc::IDynamicObject* payload /* takes ownership */,
+                          BasicSdlApplicationContext& context);
 
     virtual void Execute();
   };