tls.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: wx/os2/tls.h
  3. // Purpose: OS/2 implementation of wxTlsValue<>
  4. // Author: Stefan Neis
  5. // Created: 2008-08-30
  6. // Copyright: (c) 2008 Stefan Neis
  7. // Licence: wxWindows licence
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #ifndef _WX_OS2_TLS_H_
  10. #define _WX_OS2_TLS_H_
  11. #include "wx/os2/private.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. APIRET rc = ::DosAllocThreadLocalMemory(1, &m_slot);
  25. if (rc != NO_ERROR)
  26. m_slot = NULL;
  27. }
  28. // return true if the key was successfully allocated
  29. bool IsOk() const { return m_slot != NULL; }
  30. // get the key value, there is no error return
  31. void *Get() const
  32. {
  33. return (void *)m_slot;
  34. }
  35. // change the key value, return true if ok
  36. bool Set(void *value)
  37. {
  38. void *old = Get();
  39. m_slot = (ULONG*)value;
  40. if ( old )
  41. m_destructor(old);
  42. // update m_allValues list of all values - remove old, add new
  43. wxCriticalSectionLocker lock(m_csAllValues);
  44. if ( old )
  45. {
  46. for ( wxVector<void*>::iterator i = m_allValues.begin();
  47. i != m_allValues.end();
  48. ++i )
  49. {
  50. if ( *i == old )
  51. {
  52. if ( value )
  53. *i = value;
  54. else
  55. m_allValues.erase(i);
  56. return true;
  57. }
  58. }
  59. wxFAIL_MSG( "previous wxTlsKey value not recorded in m_allValues" );
  60. }
  61. if ( value )
  62. m_allValues.push_back(value);
  63. return true;
  64. }
  65. // free the key
  66. ~wxTlsKey()
  67. {
  68. if ( !IsOk() )
  69. return;
  70. // Win32 and OS/2 API doesn't have the equivalent of pthread's
  71. // destructor, so we have to keep track of all allocated values and
  72. // destroy them manually; ideally we'd do that at thread exit time, but
  73. // since we could only do that with wxThread and not otherwise created
  74. // threads, we do it here.
  75. //
  76. // TODO: We should still call destructors for wxTlsKey used in the
  77. // thread from wxThread's thread shutdown code, *in addition*
  78. // to doing it in ~wxTlsKey.
  79. //
  80. // NB: No need to lock m_csAllValues, by the time this code is called,
  81. // no other thread can be using this key.
  82. for ( wxVector<void*>::iterator i = m_allValues.begin();
  83. i != m_allValues.end();
  84. ++i )
  85. {
  86. m_destructor(*i);
  87. }
  88. ::DosFreeThreadLocalMemory(m_slot);
  89. }
  90. private:
  91. wxTlsDestructorFunction m_destructor;
  92. ULONG* m_slot;
  93. wxVector<void*> m_allValues;
  94. wxCriticalSection m_csAllValues;
  95. wxDECLARE_NO_COPY_CLASS(wxTlsKey);
  96. };
  97. #endif // _WX_OS2_TLS_H_