Mercurial > hg > orthanc-webviewer
comparison Plugin/Plugin.cpp @ 75:e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 23 Sep 2015 13:33:07 +0200 |
parents | ab5218c18b7a |
children | abdde1dfb3eb |
comparison
equal
deleted
inserted
replaced
74:ab5218c18b7a | 75:e15a59a4b4d4 |
---|---|
40 # define RETURN_SUCCESS 0 | 40 # define RETURN_SUCCESS 0 |
41 # define RETURN_FAILURE -1 | 41 # define RETURN_FAILURE -1 |
42 #endif | 42 #endif |
43 | 43 |
44 | 44 |
45 static OrthancPluginContext* context_ = NULL; | |
46 | |
47 | |
48 | |
45 class CacheContext | 49 class CacheContext |
46 { | 50 { |
47 private: | 51 private: |
52 class DynamicString : public Orthanc::IDynamicObject | |
53 { | |
54 private: | |
55 std::string value_; | |
56 | |
57 public: | |
58 DynamicString(const char* value) : value_(value) | |
59 { | |
60 } | |
61 | |
62 const std::string& GetValue() const | |
63 { | |
64 return value_; | |
65 } | |
66 }; | |
67 | |
48 Orthanc::FilesystemStorage storage_; | 68 Orthanc::FilesystemStorage storage_; |
49 Orthanc::SQLite::Connection db_; | 69 Orthanc::SQLite::Connection db_; |
50 | 70 |
51 std::auto_ptr<OrthancPlugins::CacheManager> cache_; | 71 std::auto_ptr<OrthancPlugins::CacheManager> cache_; |
52 std::auto_ptr<OrthancPlugins::CacheScheduler> scheduler_; | 72 std::auto_ptr<OrthancPlugins::CacheScheduler> scheduler_; |
53 | 73 |
74 Orthanc::SharedMessageQueue newInstances_; | |
75 bool stop_; | |
76 boost::thread newInstancesThread_; | |
77 | |
78 | |
79 static void NewInstancesThread(CacheContext* cache) | |
80 { | |
81 while (!cache->stop_) | |
82 { | |
83 std::auto_ptr<Orthanc::IDynamicObject> obj(cache->newInstances_.Dequeue(100)); | |
84 if (obj.get() != NULL) | |
85 { | |
86 const std::string& instanceId = dynamic_cast<DynamicString&>(*obj).GetValue(); | |
87 printf("[%s]\n", instanceId.c_str()); | |
88 | |
89 // On the reception of a new instance, precompute its spatial position | |
90 cache->GetScheduler().Prefetch(OrthancPlugins::CacheBundle_InstanceInformation, instanceId); | |
91 | |
92 // Indalidate the parent series of the instance | |
93 std::string uri = "/instances/" + std::string(instanceId); | |
94 Json::Value instance; | |
95 if (OrthancPlugins::GetJsonFromOrthanc(instance, context_, uri)) | |
96 { | |
97 std::string seriesId = instance["ParentSeries"].asString(); | |
98 cache->GetScheduler().Invalidate(OrthancPlugins::CacheBundle_SeriesInformation, seriesId); | |
99 } | |
100 } | |
101 } | |
102 } | |
103 | |
104 | |
54 public: | 105 public: |
55 CacheContext(const std::string& path) : storage_(path) | 106 CacheContext(const std::string& path) : storage_(path), stop_(false) |
56 { | 107 { |
57 boost::filesystem::path p(path); | 108 boost::filesystem::path p(path); |
58 db_.Open((p / "cache.db").string()); | 109 db_.Open((p / "cache.db").string()); |
59 | 110 |
60 cache_.reset(new OrthancPlugins::CacheManager(db_, storage_)); | 111 cache_.reset(new OrthancPlugins::CacheManager(db_, storage_)); |
61 //cache_->SetSanityCheckEnabled(true); // For debug | 112 //cache_->SetSanityCheckEnabled(true); // For debug |
62 | 113 |
63 scheduler_.reset(new OrthancPlugins::CacheScheduler(*cache_, 100)); | 114 scheduler_.reset(new OrthancPlugins::CacheScheduler(*cache_, 100)); |
115 | |
116 newInstancesThread_ = boost::thread(NewInstancesThread, this); | |
64 } | 117 } |
65 | 118 |
66 ~CacheContext() | 119 ~CacheContext() |
67 { | 120 { |
121 stop_ = true; | |
122 if (newInstancesThread_.joinable()) | |
123 { | |
124 newInstancesThread_.join(); | |
125 } | |
126 | |
68 scheduler_.reset(NULL); | 127 scheduler_.reset(NULL); |
69 cache_.reset(NULL); | 128 cache_.reset(NULL); |
70 } | 129 } |
71 | 130 |
72 OrthancPlugins::CacheScheduler& GetScheduler() | 131 OrthancPlugins::CacheScheduler& GetScheduler() |
73 { | 132 { |
74 return *scheduler_; | 133 return *scheduler_; |
75 } | 134 } |
135 | |
136 void SignalNewInstance(const char* instanceId) | |
137 { | |
138 newInstances_.Enqueue(new DynamicString(instanceId)); | |
139 } | |
76 }; | 140 }; |
77 | 141 |
78 | 142 |
79 static OrthancPluginContext* context_ = NULL; | 143 |
80 static CacheContext* cache_ = NULL; | 144 static CacheContext* cache_ = NULL; |
81 | 145 |
82 | 146 |
83 | 147 |
84 static RETURN_TYPE OnChangeCallback(OrthancPluginChangeType changeType, | 148 static RETURN_TYPE OnChangeCallback(OrthancPluginChangeType changeType, |
88 try | 152 try |
89 { | 153 { |
90 if (changeType == OrthancPluginChangeType_NewInstance && | 154 if (changeType == OrthancPluginChangeType_NewInstance && |
91 resourceType == OrthancPluginResourceType_Instance) | 155 resourceType == OrthancPluginResourceType_Instance) |
92 { | 156 { |
93 // On the reception of a new instance, precompute its spatial position | 157 cache_->SignalNewInstance(resourceId); |
94 cache_->GetScheduler().Prefetch(OrthancPlugins::CacheBundle_InstanceInformation, resourceId); | |
95 | |
96 // Indalidate the parent series of the instance | |
97 std::string uri = "/instances/" + std::string(resourceId); | |
98 Json::Value instance; | |
99 if (OrthancPlugins::GetJsonFromOrthanc(instance, context_, uri)) | |
100 { | |
101 std::string seriesId = instance["ParentSeries"].asString(); | |
102 cache_->GetScheduler().Invalidate(OrthancPlugins::CacheBundle_SeriesInformation, seriesId); | |
103 } | |
104 } | 158 } |
105 | 159 |
106 return RETURN_SUCCESS; | 160 return RETURN_SUCCESS; |
107 } | 161 } |
108 catch (std::runtime_error& e) | 162 catch (std::runtime_error& e) |