tls.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: wx/msw/tls.h
  3. // Purpose: Win32 implementation of wxTlsValue<>
  4. // Author: Vadim Zeitlin
  5. // Created: 2008-08-08
  6. // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
  7. // Licence: wxWindows licence
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #ifndef _WX_MSW_TLS_H_
  10. #define _WX_MSW_TLS_H_
  11. #include "wx/msw/wrapwin.h"
  12. #include "wx/thread.h"
  13. #include "wx/vector.h"
  14. // ----------------------------------------------------------------------------
  15. // wxTlsKey is a helper class encapsulating a TLS slot
  16. // ----------------------------------------------------------------------------
  17. class wxTlsKey
  18. {
  19. public:
  20. // ctor allocates a new key
  21. wxTlsKey(wxTlsDestructorFunction destructor)
  22. {
  23. m_destructor = destructor;
  24. m_slot = ::TlsAlloc();
  25. }
  26. // return true if the key was successfully allocated
  27. bool IsOk() const { return m_slot != TLS_OUT_OF_INDEXES; }
  28. // get the key value, there is no error return
  29. void *Get() const
  30. {
  31. return ::TlsGetValue(m_slot);
  32. }
  33. // change the key value, return true if ok
  34. bool Set(void *value)
  35. {
  36. void *old = Get();
  37. if ( ::TlsSetValue(m_slot, value) == 0 )
  38. return false;
  39. if ( old )
  40. m_destructor(old);
  41. // update m_allValues list of all values - remove old, add new
  42. wxCriticalSectionLocker lock(m_csAllValues);
  43. if ( old )
  44. {
  45. for ( wxVector<void*>::iterator i = m_allValues.begin();
  46. i != m_allValues.end();
  47. ++i )
  48. {
  49. if ( *i == old )
  50. {
  51. if ( value )
  52. *i = value;
  53. else
  54. m_allValues.erase(i);
  55. return true;
  56. }
  57. }
  58. wxFAIL_MSG( "previous wxTlsKey value not recorded in m_allValues" );
  59. }
  60. if ( value )
  61. m_allValues.push_back(value);
  62. return true;
  63. }
  64. // free the key
  65. ~wxTlsKey()
  66. {
  67. if ( !IsOk() )
  68. return;
  69. // Win32 API doesn't have the equivalent of pthread's destructor, so we
  70. // have to keep track of all allocated values and destroy them manually;
  71. // ideally we'd do that at thread exit time, but since we could only
  72. // do that with wxThread and not otherwise created threads, we do it
  73. // here.
  74. //
  75. // TODO: We should still call destructors for wxTlsKey used in the
  76. // thread from wxThread's thread shutdown code, *in addition*
  77. // to doing it in ~wxTlsKey.
  78. //
  79. // NB: No need to lock m_csAllValues, by the time this code is called,
  80. // no other thread can be using this key.
  81. for ( wxVector<void*>::iterator i = m_allValues.begin();
  82. i != m_allValues.end();
  83. ++i )
  84. {
  85. m_destructor(*i);
  86. }
  87. ::TlsFree(m_slot);
  88. }
  89. private:
  90. wxTlsDestructorFunction m_destructor;
  91. DWORD m_slot;
  92. wxVector<void*> m_allValues;
  93. wxCriticalSection m_csAllValues;
  94. wxDECLARE_NO_COPY_CLASS(wxTlsKey);
  95. };
  96. #endif // _WX_MSW_TLS_H_