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