Mercurial > hg > vamp-plugin-sdk
comparison src/vamp-sdk/PluginAdapter.cpp @ 527:bc5e76e90e95 c++11-mutex
A better way, I think, of handling static initialisation order
author | Chris Cannam |
---|---|
date | Wed, 11 Sep 2019 14:55:16 +0100 |
parents | 8c18bdaad04f |
children | db2cd87cef6f |
comparison
equal
deleted
inserted
replaced
526:459cddd7e64a | 527:bc5e76e90e95 |
---|---|
110 void checkOutputMap(Plugin *plugin); | 110 void checkOutputMap(Plugin *plugin); |
111 void markOutputsChanged(Plugin *plugin); | 111 void markOutputsChanged(Plugin *plugin); |
112 | 112 |
113 void cleanup(Plugin *plugin); | 113 void cleanup(Plugin *plugin); |
114 unsigned int getOutputCount(Plugin *plugin); | 114 unsigned int getOutputCount(Plugin *plugin); |
115 VampOutputDescriptor *getOutputDescriptor(Plugin *plugin, | 115 VampOutputDescriptor *getOutputDescriptor(Plugin *plugin, unsigned int i); |
116 unsigned int i); | |
117 VampFeatureList *process(Plugin *plugin, | 116 VampFeatureList *process(Plugin *plugin, |
118 const float *const *inputBuffers, | 117 const float *const *inputBuffers, |
119 int sec, int nsec); | 118 int sec, int nsec); |
120 VampFeatureList *getRemainingFeatures(Plugin *plugin); | 119 VampFeatureList *getRemainingFeatures(Plugin *plugin); |
121 VampFeatureList *convertFeatures(Plugin *plugin, | 120 VampFeatureList *convertFeatures(Plugin *plugin, |
122 const Plugin::FeatureSet &features); | 121 const Plugin::FeatureSet &features); |
123 | 122 |
124 // maps both plugins and descriptors to adapters | 123 // maps both plugins and descriptors to adapters |
125 typedef map<const void *, Impl *> AdapterMap; | 124 typedef map<const void *, Impl *> AdapterMap; |
125 | |
126 static AdapterMap *m_adapterMap; | 126 static AdapterMap *m_adapterMap; |
127 static mutex *m_adapterMapMutex; | 127 |
128 static mutex &adapterMapMutex() { | |
129 // If this mutex was a global static, then it might be | |
130 // destroyed before the last adapter, and we would end up | |
131 // trying to lock an invalid mutex when removing an adapter | |
132 // from the adapter map. To ensure it outlasts the adapters, | |
133 // we need to ensure it is constructed before the construction | |
134 // of any of them is complete, since destruction order is | |
135 // reverse of construction. So we have to make sure this is | |
136 // called from the PluginAdapterBase::Impl constructor below. | |
137 static mutex m; | |
138 return m; | |
139 } | |
140 | |
128 static Impl *lookupAdapter(VampPluginHandle); | 141 static Impl *lookupAdapter(VampPluginHandle); |
129 | 142 |
130 mutex m_mutex; // guards all of the below | 143 mutex m_mutex; // guards all of the below |
131 | 144 |
132 bool m_populated; | 145 bool m_populated; |
166 m_populated(false) | 179 m_populated(false) |
167 { | 180 { |
168 #ifdef DEBUG_PLUGIN_ADAPTER | 181 #ifdef DEBUG_PLUGIN_ADAPTER |
169 cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << endl; | 182 cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << endl; |
170 #endif | 183 #endif |
184 | |
185 (void)adapterMapMutex(); // see comment in adapterMapMutex function above | |
171 } | 186 } |
172 | 187 |
173 const VampPluginDescriptor * | 188 const VampPluginDescriptor * |
174 PluginAdapterBase::Impl::getDescriptor() | 189 PluginAdapterBase::Impl::getDescriptor() |
175 { | 190 { |
273 m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor; | 288 m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor; |
274 m_descriptor.process = vampProcess; | 289 m_descriptor.process = vampProcess; |
275 m_descriptor.getRemainingFeatures = vampGetRemainingFeatures; | 290 m_descriptor.getRemainingFeatures = vampGetRemainingFeatures; |
276 m_descriptor.releaseFeatureSet = vampReleaseFeatureSet; | 291 m_descriptor.releaseFeatureSet = vampReleaseFeatureSet; |
277 | 292 |
278 lock_guard<mutex> adapterMapGuard(*m_adapterMapMutex); | 293 lock_guard<mutex> adapterMapGuard(adapterMapMutex()); |
279 | 294 |
280 if (!m_adapterMap) { | 295 if (!m_adapterMap) { |
281 m_adapterMap = new AdapterMap; | 296 m_adapterMap = new AdapterMap; |
282 } | 297 } |
283 (*m_adapterMap)[&m_descriptor] = this; | 298 (*m_adapterMap)[&m_descriptor] = this; |
323 for (unsigned int i = 0; i < m_descriptor.programCount; ++i) { | 338 for (unsigned int i = 0; i < m_descriptor.programCount; ++i) { |
324 free((void *)m_descriptor.programs[i]); | 339 free((void *)m_descriptor.programs[i]); |
325 } | 340 } |
326 free((void *)m_descriptor.programs); | 341 free((void *)m_descriptor.programs); |
327 | 342 |
328 lock_guard<mutex> adapterMapGuard(*m_adapterMapMutex); | 343 lock_guard<mutex> adapterMapGuard(adapterMapMutex()); |
329 | 344 |
330 if (m_adapterMap) { | 345 if (m_adapterMap) { |
331 | 346 |
332 m_adapterMap->erase(&m_descriptor); | 347 m_adapterMap->erase(&m_descriptor); |
333 | 348 |
343 { | 358 { |
344 #ifdef DEBUG_PLUGIN_ADAPTER | 359 #ifdef DEBUG_PLUGIN_ADAPTER |
345 cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << endl; | 360 cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << endl; |
346 #endif | 361 #endif |
347 | 362 |
348 lock_guard<mutex> adapterMapGuard(*m_adapterMapMutex); | 363 lock_guard<mutex> adapterMapGuard(adapterMapMutex()); |
349 | 364 |
350 if (!m_adapterMap) return 0; | 365 if (!m_adapterMap) return 0; |
351 AdapterMap::const_iterator i = m_adapterMap->find(handle); | 366 AdapterMap::const_iterator i = m_adapterMap->find(handle); |
352 if (i == m_adapterMap->end()) return 0; | 367 if (i == m_adapterMap->end()) return 0; |
353 return i->second; | 368 return i->second; |
359 { | 374 { |
360 #ifdef DEBUG_PLUGIN_ADAPTER | 375 #ifdef DEBUG_PLUGIN_ADAPTER |
361 cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << endl; | 376 cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << endl; |
362 #endif | 377 #endif |
363 | 378 |
364 lock_guard<mutex> adapterMapGuard(*m_adapterMapMutex); | 379 lock_guard<mutex> adapterMapGuard(adapterMapMutex()); |
365 | 380 |
366 if (!m_adapterMap) { | 381 if (!m_adapterMap) { |
367 m_adapterMap = new AdapterMap(); | 382 m_adapterMap = new AdapterMap(); |
368 } | 383 } |
369 | 384 |
623 void | 638 void |
624 PluginAdapterBase::Impl::cleanup(Plugin *plugin) | 639 PluginAdapterBase::Impl::cleanup(Plugin *plugin) |
625 { | 640 { |
626 // at this point no mutex is held | 641 // at this point no mutex is held |
627 | 642 |
628 lock_guard<mutex> adapterMapGuard(*m_adapterMapMutex); | 643 lock_guard<mutex> adapterMapGuard(adapterMapMutex()); |
629 lock_guard<mutex> guard(m_mutex); | 644 lock_guard<mutex> guard(m_mutex); |
630 | 645 |
631 if (m_fs.find(plugin) != m_fs.end()) { | 646 if (m_fs.find(plugin) != m_fs.end()) { |
632 size_t outputCount = 0; | 647 size_t outputCount = 0; |
633 if (m_pluginOutputs[plugin]) { | 648 if (m_pluginOutputs[plugin]) { |
988 } | 1003 } |
989 | 1004 |
990 PluginAdapterBase::Impl::AdapterMap * | 1005 PluginAdapterBase::Impl::AdapterMap * |
991 PluginAdapterBase::Impl::m_adapterMap = 0; | 1006 PluginAdapterBase::Impl::m_adapterMap = 0; |
992 | 1007 |
993 // This is allocated on the heap so that we can be sure it outlives | |
994 // the adapters themselves, which are typically static within the | |
995 // plugin library. If this was also static, then it might be destroyed | |
996 // before the last adapter, and we would end up trying to lock an | |
997 // invalid mutex when removing an adapter from the adapter map. | |
998 mutex * | |
999 PluginAdapterBase::Impl::m_adapterMapMutex = new mutex; | |
1000 | |
1001 } | 1008 } |
1002 | 1009 |
1003 _VAMP_SDK_PLUGSPACE_END(PluginAdapter.cpp) | 1010 _VAMP_SDK_PLUGSPACE_END(PluginAdapter.cpp) |
1004 | 1011 |