| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 3433c2c commit 55d76c1
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -248,7 +248,7 @@ void DetachAllObservers(const TSubject& subject) | |||
| 248 | 248 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 249 | 249 | inline void DetachThisObserver() | |
| 250 | 250 | { | |
| 251 | - REACT_IMPL::GlobalObserverState<>::ShouldDetach = true; | ||
| 251 | + REACT_IMPL::ThreadLocalObserverState<>::ShouldDetach = true; | ||
| 252 | 252 | } | |
| 253 | 253 | ||
| 254 | 254 | /******************************************/ REACT_END /******************************************/ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,7 +17,6 @@ | |||
| 17 | 17 | #include <utility> | |
| 18 | 18 | #include <vector> | |
| 19 | 19 | ||
| 20 | - #include "tbb/concurrent_vector.h" | ||
| 21 | 20 | #include "tbb/queuing_mutex.h" | |
| 22 | 21 | ||
| 23 | 22 | #include "react/common/Concurrency.h" | |
@@ -26,7 +25,6 @@ | |||
| 26 | 25 | #include "react/detail/IReactiveNode.h" | |
| 27 | 26 | #include "react/detail/IReactiveEngine.h" | |
| 28 | 27 | #include "react/detail/ObserverBase.h" | |
| 29 | - #include "react/detail/Options.h" | ||
| 30 | 28 | ||
| 31 | 29 | /***************************************/ REACT_IMPL_BEGIN /**************************************/ | |
| 32 | 30 | ||
@@ -36,120 +34,15 @@ | |||
| 36 | 34 | template <bool is_thread_safe> | |
| 37 | 35 | class TurnBase | |
| 38 | 36 | { | |
| 39 | - public: | ||
| 40 | - TurnBase(TurnIdT id, TurnFlagsT flags); | ||
| 41 | - | ||
| 42 | - TurnIdT Id() const; | ||
| 43 | - | ||
| 44 | - void QueueForDetach(IObserver& obs); | ||
| 45 | - | ||
| 46 | - template <typename D> | ||
| 47 | - friend class InputManager; | ||
| 48 | - | ||
| 49 | - template <typename D> | ||
| 50 | - friend class ContinuationHolder; | ||
| 51 | - | ||
| 52 | - private: | ||
| 53 | - using ContinuationT = ContinuationInput<is_thread_safe>; | ||
| 54 | - | ||
| 55 | - template <typename D> | ||
| 56 | - void detachObservers(); | ||
| 57 | - }; | ||
| 58 | - | ||
| 59 | - // Not thread-safe | ||
| 60 | - template <> | ||
| 61 | - class TurnBase<false> | ||
| 62 | - { | ||
| 63 | - public: | ||
| 64 | - TurnBase(TurnIdT id, TurnFlagsT flags) : | ||
| 65 | - id_( id ) | ||
| 66 | - {} | ||
| 67 | - | ||
| 68 | - TurnIdT Id() const { return id_; } | ||
| 69 | - | ||
| 70 | - void QueueForDetach(IObserver& obs) | ||
| 71 | - { | ||
| 72 | - detachedObservers_.push_back(&obs); | ||
| 73 | - } | ||
| 74 | - | ||
| 75 | - template <typename D> | ||
| 76 | - friend class InputManager; | ||
| 77 | - | ||
| 78 | - template <typename D> | ||
| 79 | - friend class ContinuationHolder; | ||
| 80 | - | ||
| 81 | - private: | ||
| 82 | - using ObsVectT = std::vector<IObserver*>; | ||
| 83 | - using ContinuationT = ContinuationInput<false>; | ||
| 84 | - | ||
| 85 | - TurnIdT id_; | ||
| 86 | - | ||
| 87 | - template <typename D> | ||
| 88 | - void detachObservers() | ||
| 89 | - { | ||
| 90 | - | ||
| 91 | - auto& registry = DomainSpecificObserverRegistry<D>::Instance(); | ||
| 92 | - | ||
| 93 | - for (auto* o : detachedObservers_) | ||
| 94 | - registry.Unregister(o); | ||
| 95 | - | ||
| 96 | - detachedObservers_.clear(); | ||
| 97 | - } | ||
| 98 | - | ||
| 99 | - ObsVectT detachedObservers_; | ||
| 100 | - ContinuationT continuation_; | ||
| 101 | - }; | ||
| 102 | - | ||
| 103 | - // Thread-safe | ||
| 104 | - template <> | ||
| 105 | - class TurnBase<true> | ||
| 106 | - { | ||
| 107 | 37 | public: | |
| 108 | 38 | TurnBase(TurnIdT id, TurnFlagsT flags) : | |
| 109 | 39 | id_( id ) | |
| 110 | 40 | {} | |
| 111 | 41 | ||
| 112 | 42 | TurnIdT Id() const { return id_; } | |
| 113 | 43 | ||
| 114 | - void QueueForDetach(IObserver& obs) | ||
| 115 | - { | ||
| 116 | - // Allocation of concurrent vector is not cheap -> create on demand | ||
| 117 | - std::call_once(detachedObserversInit_, [this] { | ||
| 118 | - detachedObserversPtr_.reset(new ObsVectT()); | ||
| 119 | - }); | ||
| 120 | - | ||
| 121 | - detachedObserversPtr_->push_back(&obs); | ||
| 122 | - } | ||
| 123 | - | ||
| 124 | - template <typename D> | ||
| 125 | - friend class InputManager; | ||
| 126 | - | ||
| 127 | - template <typename D> | ||
| 128 | - friend class ContinuationHolder; | ||
| 129 | - | ||
| 130 | 44 | private: | |
| 131 | - using ObsVectT = tbb::concurrent_vector<IObserver*>; | ||
| 132 | - using ContinuationT = ContinuationInput<true>; | ||
| 133 | - | ||
| 134 | 45 | TurnIdT id_; | |
| 135 | - | ||
| 136 | - template <typename D> | ||
| 137 | - void detachObservers() | ||
| 138 | - { | ||
| 139 | - if (detachedObserversPtr_ != nullptr) | ||
| 140 | - { | ||
| 141 | - auto& registry = DomainSpecificObserverRegistry<D>::Instance(); | ||
| 142 | - | ||
| 143 | - for (auto* o : *detachedObserversPtr_) | ||
| 144 | - registry.Unregister(o); | ||
| 145 | - | ||
| 146 | - detachedObserversPtr_->clear(); | ||
| 147 | - } | ||
| 148 | - } | ||
| 149 | - | ||
| 150 | - std::once_flag detachedObserversInit_; | ||
| 151 | - std::unique_ptr<ObsVectT> detachedObserversPtr_; | ||
| 152 | - ContinuationT continuation_; | ||
| 153 | 46 | }; | |
| 154 | 47 | ||
| 155 | 48 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
@@ -179,21 +72,33 @@ class TurnQueueManager | |||
| 179 | 72 | inline void RunMergedInputs() const | |
| 180 | 73 | { | |
| 181 | 74 | for (const auto& e : merged_) | |
| 182 | - e.first(); | ||
| 75 | + e.InputFunc(); | ||
| 183 | 76 | } | |
| 184 | 77 | ||
| 185 | 78 | inline void UnblockSuccessors() | |
| 186 | 79 | { | |
| 80 | + // Release merged | ||
| 187 | 81 | for (const auto& e : merged_) | |
| 188 | - if (e.second != nullptr) | ||
| 189 | - e.second->Unblock(); | ||
| 82 | + { | ||
| 83 | + // Note: Since a merged input is either sync or async, | ||
| 84 | + // either cond or status will be null | ||
| 190 | 85 | ||
| 86 | + // Sync | ||
| 87 | + if (e.Cond != nullptr) | ||
| 88 | + e.Cond->Unblock(); | ||
| 89 | + | ||
| 90 | + // Async | ||
| 91 | + else if (e.Status != nullptr) | ||
| 92 | + TransactionStatusInterface::DecrementWaitCount(*e.Status); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + // Release next thread in queue | ||
| 191 | 96 | if (successor_) | |
| 192 | 97 | successor_->blockCondition_.Unblock(); | |
| 193 | 98 | } | |
| 194 | 99 | ||
| 195 | 100 | template <typename F> | |
| 196 | - inline bool TryMerge(F&& inputFunc, BlockingCondition* caller) | ||
| 101 | + inline bool TryMerge(F&& inputFunc, BlockingCondition* caller, TransactionStatus* status) | ||
| 197 | 102 | { | |
| 198 | 103 | if (!isMergeable_) | |
| 199 | 104 | return false; | |
@@ -202,18 +107,32 @@ class TurnQueueManager | |||
| 202 | 107 | bool merged = blockCondition_.RunIfBlocked([&] { | |
| 203 | 108 | if (caller) | |
| 204 | 109 | caller->Block(); | |
| 205 | - merged_.emplace_back(std::make_pair(std::forward<F>(inputFunc), caller)); | ||
| 110 | + merged_.emplace_back(std::forward<F>(inputFunc), caller, status); | ||
| 206 | 111 | }); | |
| 207 | 112 | ||
| 208 | 113 | return merged; | |
| 209 | 114 | } | |
| 210 | 115 | ||
| 211 | 116 | private: | |
| 212 | - using MergedDataVectT = | ||
| 213 | - std::vector< | ||
| 214 | - std::pair< | ||
| 215 | - std::function<void()>, | ||
| 216 | - BlockingCondition*>>; | ||
| 117 | + struct MergedData | ||
| 118 | + { | ||
| 119 | + template <typename F> | ||
| 120 | + MergedData(F&& func, BlockingCondition* cond, TransactionStatus* status) : | ||
| 121 | + InputFunc( std::forward<F>(func) ), | ||
| 122 | + Cond( cond ), | ||
| 123 | + Status( status ) | ||
| 124 | + {} | ||
| 125 | + | ||
| 126 | + std::function<void()> InputFunc; | ||
| 127 | + | ||
| 128 | + // Blocking condition variable for sync merged | ||
| 129 | + BlockingCondition* Cond; | ||
| 130 | + | ||
| 131 | + // Status for async merged | ||
| 132 | + TransactionStatus* Status; | ||
| 133 | + }; | ||
| 134 | + | ||
| 135 | + using MergedDataVectT = std::vector<MergedData>; | ||
| 217 | 136 | ||
| 218 | 137 | bool isMergeable_; | |
| 219 | 138 | QueueEntry* successor_ = nullptr; | |
@@ -222,7 +141,7 @@ class TurnQueueManager | |||
| 222 | 141 | }; | |
| 223 | 142 | ||
| 224 | 143 | template <typename F> | |
| 225 | - inline bool TryMerge(F&& inputFunc) | ||
| 144 | + inline bool TryMergeSync(F&& inputFunc) | ||
| 226 | 145 | { | |
| 227 | 146 | bool merged = false; | |
| 228 | 147 | ||
@@ -232,7 +151,7 @@ class TurnQueueManager | |||
| 232 | 151 | SeqMutexT::scoped_lock lock(seqMutex_); | |
| 233 | 152 | ||
| 234 | 153 | if (tail_) | |
| 235 | - merged = tail_->TryMerge(std::forward<F>(inputFunc), &caller); | ||
| 154 | + merged = tail_->TryMerge(std::forward<F>(inputFunc), &caller, nullptr); | ||
| 236 | 155 | }// ~seqMutex_ | |
| 237 | 156 | ||
| 238 | 157 | if (merged) | |
@@ -242,15 +161,15 @@ class TurnQueueManager | |||
| 242 | 161 | } | |
| 243 | 162 | ||
| 244 | 163 | template <typename F> | |
| 245 | - inline bool TryMergeAsync(F&& inputFunc) | ||
| 164 | + inline bool TryMergeAsync(F&& inputFunc, TransactionStatus* status) | ||
| 246 | 165 | { | |
| 247 | 166 | bool merged = false; | |
| 248 | 167 | ||
| 249 | 168 | {// seqMutex_ | |
| 250 | 169 | SeqMutexT::scoped_lock lock(seqMutex_); | |
| 251 | 170 | ||
| 252 | 171 | if (tail_) | |
| 253 | - merged = tail_->TryMerge(std::forward<F>(inputFunc), nullptr); | ||
| 172 | + merged = tail_->TryMerge(std::forward<F>(inputFunc), nullptr, status); | ||
| 254 | 173 | }// ~seqMutex_ | |
| 255 | 174 | ||
| 256 | 175 | return merged; | |
@@ -316,12 +235,15 @@ class DefaultQueuingEngine : public TTEngineBase<DefaultQueueableTurn<TTurnBase> | |||
| 316 | 235 | using TurnT = DefaultQueueableTurn<TTurnBase>; | |
| 317 | 236 | ||
| 318 | 237 | template <typename F> | |
| 319 | - bool TryMergeInput(F&& f, bool isBlocking) | ||
| 238 | + bool TryMergeSync(F&& f) | ||
| 239 | + { | ||
| 240 | + return queueManager_.TryMergeSync(std::forward<F>(f)); | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | + template <typename F> | ||
| 244 | + bool TryMergeAsync(F&& f, TransactionStatus* statusPtr) | ||
| 320 | 245 | { | |
| 321 | - if (isBlocking) | ||
| 322 | - return queueManager_.TryMerge(std::forward<F>(f)); | ||
| 323 | - else | ||
| 324 | - return queueManager_.TryMergeAsync(std::forward<F>(f)); | ||
| 246 | + return queueManager_.TryMergeAsync(std::forward<F>(f), statusPtr); | ||
| 325 | 247 | } | |
| 326 | 248 | ||
| 327 | 249 | void ApplyMergedInputs(TurnT& turn) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,6 +17,11 @@ | |||
| 17 | 17 | ||
| 18 | 18 | /***************************************/ REACT_IMPL_BEGIN /**************************************/ | |
| 19 | 19 | ||
| 20 | + /////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 21 | + /// Forward declarations | ||
| 22 | + /////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 23 | + class TransactionStatus; | ||
| 24 | + | ||
| 20 | 25 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 21 | 26 | /// IReactiveEngine | |
| 22 | 27 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
@@ -31,7 +36,10 @@ struct IReactiveEngine | |||
| 31 | 36 | using TurnT = TTurn; | |
| 32 | 37 | ||
| 33 | 38 | template <typename F> | |
| 34 | - bool TryMergeInput(F&& f, bool isBlocking) { return false; } | ||
| 39 | + bool TryMergeSync(F&& f) { return false; } | ||
| 40 | + | ||
| 41 | + template <typename F> | ||
| 42 | + bool TryMergeAsync(F&& f, TransactionStatus* status) { return false; } | ||
| 35 | 43 | ||
| 36 | 44 | void ApplyMergedInputs(TurnT& turn) {} | |
| 37 | 45 | ||
@@ -78,9 +86,15 @@ struct EngineInterface | |||
| 78 | 86 | } | |
| 79 | 87 | ||
| 80 | 88 | template <typename F> | |
| 81 | - static bool TryMergeInput(F&& f, bool isBlocking) | ||
| 89 | + static bool TryMergeSync(F&& f) | ||
| 90 | + { | ||
| 91 | + return Instance().TryMergeSync(std::forward<F>(f)); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + template <typename F> | ||
| 95 | + static bool TryMergeAsync(F&& f, TransactionStatus* status) | ||
| 82 | 96 | { | |
| 83 | - return Instance().TryMergeInput(std::forward<F>(f), isBlocking); | ||
| 97 | + return Instance().TryMergeAsync(std::forward<F>(f), status); | ||
| 84 | 98 | } | |
| 85 | 99 | ||
| 86 | 100 | static void ApplyMergedInputs(TurnT& turn) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,13 +40,13 @@ class IObserver | |||
| 40 | 40 | ||
| 41 | 41 | // tbb tasks are non-preemptible, thread local flag for each worker | |
| 42 | 42 | template <typename = void> | |
| 43 | - struct GlobalObserverState | ||
| 43 | + struct ThreadLocalObserverState | ||
| 44 | 44 | { | |
| 45 | 45 | static REACT_TLS bool ShouldDetach; | |
| 46 | 46 | }; | |
| 47 | 47 | ||
| 48 | 48 | template <typename T> | |
| 49 | - REACT_TLS bool GlobalObserverState<T>::ShouldDetach(false); | ||
| 49 | + REACT_TLS bool ThreadLocalObserverState<T>::ShouldDetach(false); | ||
| 50 | 50 | ||
| 51 | 51 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 52 | 52 | /// ObserverRegistry | |
| Back | FazBrowse Home | New Git URL |
0 commit comments