2 * Copyright 2015 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #if !defined(ANDROID) && !defined(__ANDROID__) && !defined(__APPLE__)
19 #include <folly/io/async/EventBaseLocal.h>
23 namespace folly { namespace detail {
25 EventBaseLocalBase::~EventBaseLocalBase() {
26 // There's a race condition if an EventBase and an EventBaseLocal destruct
27 // at the same time (each will lock eventBases_ and localStorageMutex_
28 // in the opposite order), so we dance around it with a loop and try_lock.
30 SYNCHRONIZED(eventBases_) {
31 auto it = eventBases_.begin();
32 while (it != eventBases_.end()) {
34 if (evb->localStorageMutex_.try_lock()) {
35 evb->localStorage_.erase(key_);
36 evb->localStorageToDtor_.erase(this);
37 it = eventBases_.erase(it);
38 evb->localStorageMutex_.unlock();
44 if (eventBases_.empty()) {
48 std::this_thread::yield(); // let the other thread take the eventBases_ lock
52 void* EventBaseLocalBase::getVoid(EventBase& evb) {
53 std::lock_guard<std::mutex> lg(evb.localStorageMutex_);
54 auto it2 = evb.localStorage_.find(key_);
55 if (UNLIKELY(it2 != evb.localStorage_.end())) {
56 return it2->second.get();
62 void EventBaseLocalBase::erase(EventBase& evb) {
63 std::lock_guard<std::mutex> lg(evb.localStorageMutex_);
64 evb.localStorage_.erase(key_);
65 evb.localStorageToDtor_.erase(this);
67 SYNCHRONIZED(eventBases_) {
68 eventBases_.erase(&evb);
72 void EventBaseLocalBase::onEventBaseDestruction(EventBase& evb) {
73 SYNCHRONIZED(eventBases_) {
74 eventBases_.erase(&evb);
78 void EventBaseLocalBase::setVoid(EventBase& evb, std::shared_ptr<void>&& ptr) {
79 std::lock_guard<std::mutex> lg(evb.localStorageMutex_);
80 setVoidUnlocked(evb, std::move(ptr));
83 void EventBaseLocalBase::setVoidUnlocked(
84 EventBase& evb, std::shared_ptr<void>&& ptr) {
87 evb.localStorage_.find(key_) != evb.localStorage_.end();
89 evb.localStorage_.emplace(key_, std::move(ptr));
92 SYNCHRONIZED(eventBases_) {
93 eventBases_.insert(&evb);
95 evb.localStorageToDtor_.insert(this);
99 std::atomic<uint64_t> EventBaseLocalBase::keyCounter_{0};
102 #endif // !__ANDROID__ && !ANDROID && !__APPLE__