Copyright 2014->2015
[folly.git] / folly / wangle / concurrent / GlobalExecutor.cpp
1 /*
2  * Copyright 2015 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 <folly/experimental/Singleton.h>
18 #include <folly/wangle/concurrent/IOExecutor.h>
19 #include <folly/wangle/concurrent/IOThreadPoolExecutor.h>
20 #include <folly/futures/InlineExecutor.h>
21
22 using namespace folly;
23 using namespace folly::wangle;
24
25 namespace {
26
27 // lock protecting global CPU executor
28 struct CPUExecutorLock {};
29 Singleton<RWSpinLock, CPUExecutorLock> globalCPUExecutorLock;
30 // global CPU executor
31 Singleton<std::weak_ptr<Executor>> globalCPUExecutor;
32 // default global CPU executor is an InlineExecutor
33 Singleton<std::shared_ptr<InlineExecutor>> globalInlineExecutor(
34     []{
35       return new std::shared_ptr<InlineExecutor>(
36           std::make_shared<InlineExecutor>());
37     });
38
39 // lock protecting global IO executor
40 struct IOExecutorLock {};
41 Singleton<RWSpinLock, IOExecutorLock> globalIOExecutorLock;
42 // global IO executor
43 Singleton<std::weak_ptr<IOExecutor>> globalIOExecutor;
44 // default global IO executor is an IOThreadPoolExecutor
45 Singleton<std::shared_ptr<IOThreadPoolExecutor>> globalIOThreadPool(
46     []{
47       return new std::shared_ptr<IOThreadPoolExecutor>(
48           std::make_shared<IOThreadPoolExecutor>(
49               sysconf(_SC_NPROCESSORS_ONLN),
50               std::make_shared<NamedThreadFactory>("GlobalIOThreadPool")));
51     });
52
53 }
54
55 namespace folly { namespace wangle {
56
57 template <class Exe, class DefaultExe, class LockTag>
58 std::shared_ptr<Exe> getExecutor(
59     Singleton<std::weak_ptr<Exe>>& sExecutor,
60     Singleton<std::shared_ptr<DefaultExe>>& sDefaultExecutor,
61     Singleton<RWSpinLock, LockTag>& sExecutorLock) {
62   std::shared_ptr<Exe> executor;
63   auto singleton = sExecutor.get();
64   auto lock = sExecutorLock.get();
65
66   {
67     RWSpinLock::ReadHolder guard(lock);
68     if ((executor = sExecutor->lock())) {
69       return executor;
70     }
71   }
72
73
74   RWSpinLock::WriteHolder guard(lock);
75   executor = singleton->lock();
76   if (!executor) {
77     executor = *sDefaultExecutor.get();
78     *singleton = executor;
79   }
80   return executor;
81 }
82
83 template <class Exe, class LockTag>
84 void setExecutor(
85     std::shared_ptr<Exe> executor,
86     Singleton<std::weak_ptr<Exe>>& sExecutor,
87     Singleton<RWSpinLock, LockTag>& sExecutorLock) {
88   RWSpinLock::WriteHolder guard(sExecutorLock.get());
89   *sExecutor.get() = std::move(executor);
90 }
91
92 std::shared_ptr<Executor> getCPUExecutor() {
93   return getExecutor(
94       globalCPUExecutor,
95       globalInlineExecutor,
96       globalCPUExecutorLock);
97 }
98
99 void setCPUExecutor(std::shared_ptr<Executor> executor) {
100   setExecutor(
101       std::move(executor),
102       globalCPUExecutor,
103       globalCPUExecutorLock);
104 }
105
106 std::shared_ptr<IOExecutor> getIOExecutor() {
107   return getExecutor(
108       globalIOExecutor,
109       globalIOThreadPool,
110       globalIOExecutorLock);
111 }
112
113 void setIOExecutor(std::shared_ptr<IOExecutor> executor) {
114   setExecutor(
115       std::move(executor),
116       globalIOExecutor,
117       globalIOExecutorLock);
118 }
119
120 }} // folly::wangle