OpenShot Audio Library | OpenShotAudio  0.3.0
juce_ThreadLocalValue.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 //==============================================================================
46 template <typename Type>
48 {
49 public:
51  ThreadLocalValue() = default;
52 
57  {
58  for (auto* o = first.get(); o != nullptr;)
59  {
60  auto* next = o->next;
61  delete o;
62  o = next;
63  }
64  }
65 
71  Type& operator*() const noexcept { return get(); }
72 
78  operator Type*() const noexcept { return &get(); }
79 
85  Type* operator->() const noexcept { return &get(); }
86 
88  ThreadLocalValue& operator= (const Type& newValue) { get() = newValue; return *this; }
89 
95  Type& get() const noexcept
96  {
97  auto threadId = Thread::getCurrentThreadId();
98  ObjectHolder* o = nullptr;
99 
100  for (o = first.get(); o != nullptr; o = o->next)
101  if (o->threadId.get() == threadId)
102  return o->object;
103 
104  for (o = first.get(); o != nullptr; o = o->next)
105  if (o->threadId.compareAndSetBool (threadId, nullptr))
106  break;
107 
108  if (o != nullptr)
109  o->object = Type();
110  else
111  for (o = new ObjectHolder (threadId, first.get());
112  ! first.compareAndSetBool (o, o->next);
113  o->next = first.get());
114 
115  return o->object;
116  }
117 
122  {
123  auto threadId = Thread::getCurrentThreadId();
124 
125  for (auto* o = first.get(); o != nullptr; o = o->next)
126  if (o->threadId.compareAndSetBool (nullptr, threadId))
127  return;
128  }
129 
130 private:
131  //==============================================================================
132  struct ObjectHolder
133  {
134  ObjectHolder (Thread::ThreadID idToUse, ObjectHolder* n) : threadId (idToUse), next (n), object() {}
135 
136  Atomic<Thread::ThreadID> threadId;
137  ObjectHolder* next;
138  Type object;
139 
140  JUCE_DECLARE_NON_COPYABLE (ObjectHolder)
141  };
142 
143  mutable Atomic<ObjectHolder*> first;
144 
145  JUCE_DECLARE_NON_COPYABLE (ThreadLocalValue)
146 };
147 
148 } // namespace juce
void * ThreadID
Definition: juce_Thread.h:304
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
ThreadLocalValue & operator=(const Type &newValue)
Type get() const noexcept
Definition: juce_Atomic.h:64
Type * operator->() const noexcept
bool compareAndSetBool(Type newValue, Type valueToCompare) noexcept
Definition: juce_Atomic.h:96
Type & operator*() const noexcept