2 * Copyright 2017 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 #include <folly/Singleton.h>
18 #include <folly/executors/IOExecutor.h>
19 #include <folly/executors/IOThreadPoolExecutor.h>
20 #include <folly/futures/InlineExecutor.h>
22 using namespace folly;
26 // lock protecting global CPU executor
27 struct CPUExecutorLock {};
28 Singleton<RWSpinLock, CPUExecutorLock> globalCPUExecutorLock;
29 // global CPU executor
30 Singleton<std::weak_ptr<Executor>> globalCPUExecutor;
31 // default global CPU executor is an InlineExecutor
32 Singleton<std::shared_ptr<InlineExecutor>> globalInlineExecutor([] {
33 return new std::shared_ptr<InlineExecutor>(
34 std::make_shared<InlineExecutor>());
37 // lock protecting global IO executor
38 struct IOExecutorLock {};
39 Singleton<RWSpinLock, IOExecutorLock> globalIOExecutorLock;
41 Singleton<std::weak_ptr<IOExecutor>> globalIOExecutor;
42 // default global IO executor is an IOThreadPoolExecutor
43 Singleton<std::shared_ptr<IOThreadPoolExecutor>> globalIOThreadPool([] {
44 return new std::shared_ptr<IOThreadPoolExecutor>(
45 std::make_shared<IOThreadPoolExecutor>(
46 sysconf(_SC_NPROCESSORS_ONLN),
47 std::make_shared<NamedThreadFactory>("GlobalIOThreadPool")));
53 template <class Exe, class DefaultExe, class LockTag>
54 std::shared_ptr<Exe> getExecutor(
55 Singleton<std::weak_ptr<Exe>>& sExecutor,
56 Singleton<std::shared_ptr<DefaultExe>>& sDefaultExecutor,
57 Singleton<RWSpinLock, LockTag>& sExecutorLock) {
58 std::shared_ptr<Exe> executor;
59 auto singleton = sExecutor.try_get();
60 auto lock = sExecutorLock.try_get();
63 RWSpinLock::ReadHolder guard(lock.get());
64 if ((executor = sExecutor.try_get()->lock())) {
69 RWSpinLock::WriteHolder guard(lock.get());
70 executor = singleton->lock();
72 std::weak_ptr<Exe> defaultExecutor = *sDefaultExecutor.try_get().get();
73 executor = defaultExecutor.lock();
74 sExecutor.try_get().get()->swap(defaultExecutor);
79 template <class Exe, class LockTag>
81 std::weak_ptr<Exe> executor,
82 Singleton<std::weak_ptr<Exe>>& sExecutor,
83 Singleton<RWSpinLock, LockTag>& sExecutorLock) {
84 auto lock = sExecutorLock.try_get();
85 RWSpinLock::WriteHolder guard(*lock);
86 std::weak_ptr<Exe> executor_weak = std::move(executor);
87 sExecutor.try_get().get()->swap(executor_weak);
90 std::shared_ptr<Executor> getCPUExecutor() {
92 globalCPUExecutor, globalInlineExecutor, globalCPUExecutorLock);
95 void setCPUExecutor(std::weak_ptr<Executor> executor) {
96 setExecutor(std::move(executor), globalCPUExecutor, globalCPUExecutorLock);
99 std::shared_ptr<IOExecutor> getIOExecutor() {
101 globalIOExecutor, globalIOThreadPool, globalIOExecutorLock);
104 EventBase* getEventBase() {
105 return getIOExecutor()->getEventBase();
108 void setIOExecutor(std::weak_ptr<IOExecutor> executor) {
109 setExecutor(std::move(executor), globalIOExecutor, globalIOExecutorLock);