1 | /* |
---|---|
2 | * Copyright 2017-present Facebook, Inc. |
3 | * |
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 |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
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. |
15 | */ |
16 | |
17 | #include <memory> |
18 | #include <thread> |
19 | |
20 | #include <folly/Function.h> |
21 | #include <folly/SharedMutex.h> |
22 | #include <folly/Singleton.h> |
23 | #include <folly/executors/IOExecutor.h> |
24 | #include <folly/executors/IOThreadPoolExecutor.h> |
25 | #include <folly/executors/InlineExecutor.h> |
26 | |
27 | using namespace folly; |
28 | |
29 | namespace { |
30 | |
31 | template <class ExecutorBase> |
32 | class GlobalExecutor { |
33 | public: |
34 | explicit GlobalExecutor( |
35 | Function<std::unique_ptr<ExecutorBase>()> constructDefault) |
36 | : constructDefault_(std::move(constructDefault)) {} |
37 | |
38 | std::shared_ptr<ExecutorBase> get() { |
39 | { |
40 | SharedMutex::ReadHolder guard(mutex_); |
41 | if (auto executor = executor_.lock()) { |
42 | return executor; // Fast path. |
43 | } |
44 | } |
45 | |
46 | SharedMutex::WriteHolder guard(mutex_); |
47 | if (auto executor = executor_.lock()) { |
48 | return executor; |
49 | } |
50 | |
51 | if (!defaultExecutor_) { |
52 | defaultExecutor_ = constructDefault_(); |
53 | } |
54 | |
55 | return defaultExecutor_; |
56 | } |
57 | |
58 | void set(std::weak_ptr<ExecutorBase> executor) { |
59 | SharedMutex::WriteHolder guard(mutex_); |
60 | executor_.swap(executor); |
61 | } |
62 | |
63 | private: |
64 | SharedMutex mutex_; |
65 | std::weak_ptr<ExecutorBase> executor_; |
66 | std::shared_ptr<ExecutorBase> defaultExecutor_; |
67 | Function<std::unique_ptr<ExecutorBase>()> constructDefault_; |
68 | }; |
69 | |
70 | Singleton<GlobalExecutor<Executor>> gGlobalCPUExecutor([] { |
71 | return new GlobalExecutor<Executor>( |
72 | // Default global CPU executor is an InlineExecutor. |
73 | [] { return std::make_unique<InlineExecutor>(); }); |
74 | }); |
75 | |
76 | Singleton<GlobalExecutor<IOExecutor>> gGlobalIOExecutor([] { |
77 | return new GlobalExecutor<IOExecutor>( |
78 | // Default global IO executor is an IOThreadPoolExecutor. |
79 | [] { |
80 | return std::make_unique<IOThreadPoolExecutor>( |
81 | std::thread::hardware_concurrency(), |
82 | std::make_shared<NamedThreadFactory>("GlobalIOThreadPool")); |
83 | }); |
84 | }); |
85 | |
86 | } // namespace |
87 | |
88 | namespace folly { |
89 | |
90 | std::shared_ptr<Executor> getCPUExecutor() { |
91 | if (auto singleton = gGlobalCPUExecutor.try_get()) { |
92 | return singleton->get(); |
93 | } |
94 | return nullptr; |
95 | } |
96 | |
97 | void setCPUExecutor(std::weak_ptr<Executor> executor) { |
98 | if (auto singleton = gGlobalCPUExecutor.try_get()) { |
99 | singleton->set(std::move(executor)); |
100 | } |
101 | } |
102 | |
103 | std::shared_ptr<IOExecutor> getIOExecutor() { |
104 | if (auto singleton = gGlobalIOExecutor.try_get()) { |
105 | return singleton->get(); |
106 | } |
107 | return nullptr; |
108 | } |
109 | |
110 | void setIOExecutor(std::weak_ptr<IOExecutor> executor) { |
111 | if (auto singleton = gGlobalIOExecutor.try_get()) { |
112 | singleton->set(std::move(executor)); |
113 | } |
114 | } |
115 | |
116 | EventBase* getEventBase() { |
117 | return getIOExecutor()->getEventBase(); |
118 | } |
119 | |
120 | } // namespace folly |
121 |