The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
5.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #ifndef __JUCE_THREADLOCALVALUE_JUCEHEADER__
  19. #define __JUCE_THREADLOCALVALUE_JUCEHEADER__
  20. //==============================================================================
  21. /**
  22. Provides cross-platform support for thread-local objects.
  23. This class holds an internal list of objects of the templated type, keeping
  24. an instance for each thread that requests one. The first time a thread attempts
  25. to access its value, an object is created and added to the list for that thread.
  26. The templated class for your value could be a primitive type, or any class that
  27. has a default constructor.
  28. Once a thread has accessed its object, that object will not be deleted until the
  29. ThreadLocalValue object itself is deleted, even if its thread exits before that.
  30. But, because thread ID numbers are used to identify threads, and OSes often re-use
  31. these ID numbers, value objects will often be implicitly re-used by new threads whose
  32. ID number is the same as one that was used by an earlier thread.
  33. */
  34. template <typename Type>
  35. class ThreadLocalValue
  36. {
  37. public:
  38. /** */
  39. ThreadLocalValue() noexcept
  40. {
  41. }
  42. /** Destructor.
  43. When this object is deleted, all the value objects for all threads will be deleted.
  44. */
  45. ~ThreadLocalValue()
  46. {
  47. for (ObjectHolder* o = first.value; o != nullptr;)
  48. {
  49. ObjectHolder* const next = o->next;
  50. delete o;
  51. o = next;
  52. }
  53. }
  54. /** Returns a reference to this thread's instance of the value.
  55. Note that the first time a thread tries to access the value, an instance of the
  56. value object will be created - so if your value's class has a non-trivial
  57. constructor, be aware that this method could invoke it.
  58. */
  59. Type& operator*() const noexcept { return get(); }
  60. /** Returns a pointer to this thread's instance of the value.
  61. Note that the first time a thread tries to access the value, an instance of the
  62. value object will be created - so if your value's class has a non-trivial
  63. constructor, be aware that this method could invoke it.
  64. */
  65. operator Type*() const noexcept { return &get(); }
  66. /** Accesses a method or field of the value object.
  67. Note that the first time a thread tries to access the value, an instance of the
  68. value object will be created - so if your value's class has a non-trivial
  69. constructor, be aware that this method could invoke it.
  70. */
  71. Type* operator->() const noexcept { return &get(); }
  72. /** Returns a reference to this thread's instance of the value.
  73. Note that the first time a thread tries to access the value, an instance of the
  74. value object will be created - so if your value's class has a non-trivial
  75. constructor, be aware that this method could invoke it.
  76. */
  77. Type& get() const noexcept
  78. {
  79. const Thread::ThreadID threadId = Thread::getCurrentThreadId();
  80. for (ObjectHolder* o = first.get(); o != nullptr; o = o->next)
  81. if (o->threadId == threadId)
  82. return o->object;
  83. ObjectHolder* const newObject = new ObjectHolder (threadId);
  84. do
  85. {
  86. newObject->next = first.get();
  87. }
  88. while (! first.compareAndSetBool (newObject, newObject->next));
  89. return newObject->object;
  90. }
  91. private:
  92. //==============================================================================
  93. struct ObjectHolder
  94. {
  95. ObjectHolder (const Thread::ThreadID& threadId_)
  96. : threadId (threadId_), object()
  97. {}
  98. const Thread::ThreadID threadId;
  99. ObjectHolder* next;
  100. Type object;
  101. JUCE_DECLARE_NON_COPYABLE (ObjectHolder);
  102. };
  103. mutable Atomic<ObjectHolder*> first;
  104. JUCE_DECLARE_NON_COPYABLE (ThreadLocalValue);
  105. };
  106. #endif // __JUCE_THREADLOCALVALUE_JUCEHEADER__