3 |
4 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
5 | LPVOID lpReserved) {
6 | switch (ul_reason_for_call) {
7 | case DLL_PROCESS_ATTACH:
8 | case DLL_THREAD_ATTACH:
9 | case DLL_THREAD_DETACH:
10 | case DLL_PROCESS_DETACH:
11 | break;
12 | }
13 | return TRUE;
14 | }
15 |
--------------------------------------------------------------------------------
/EdgeView/edgeview.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Admenri/EdgeView/c556e12253ba1903dd9dca8b3993b34da2c7a33e/EdgeView/edgeview.rc
--------------------------------------------------------------------------------
/EdgeView/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/EdgeView/resource.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Admenri/EdgeView/c556e12253ba1903dd9dca8b3993b34da2c7a33e/EdgeView/resource.h
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # EdgeView
2 |
3 | ## 项目概述
4 |
5 | 本库是为易语言编写的WebView2封装调用库,已进行线程隔离,支持多线程同步调用,
6 | 同时借助CDP的功能实现原版之外的附加内容。
7 |
8 | ## 注意事项
9 |
10 | 作者QQ:2755482106
11 |
12 | 本库禁止用于违法违规用途,否则后果自负。
13 |
14 | 【付费】用户群:372404087
15 | 【说明】本库开源免费,但不代表劳动免费,如果需要额外例程教程和问题咨询,
16 | 只能付费加入用户群获取帮助,如果你认为免费是理所应当的请不要下载使用本库。
17 | 模块免费使用,作者不对此提供任何免费的技术支持非常合理。
18 | ※ 所以白嫖跳脸狗请自觉删除本库,作者产品不提供给狗使用。
19 |
20 | © 2023 Admenri
--------------------------------------------------------------------------------
/ec/EdgeView.e:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Admenri/EdgeView/c556e12253ba1903dd9dca8b3993b34da2c7a33e/ec/EdgeView.e
--------------------------------------------------------------------------------
/epltest/edgeview.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Admenri/EdgeView/c556e12253ba1903dd9dca8b3993b34da2c7a33e/epltest/edgeview.dll
--------------------------------------------------------------------------------
/epltest/edgeview.ec:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Admenri/EdgeView/c556e12253ba1903dd9dca8b3993b34da2c7a33e/epltest/edgeview.ec
--------------------------------------------------------------------------------
/epltest/使用前必读.txt:
--------------------------------------------------------------------------------
1 | EdgeView浏览器框架模块属易语言WebView2封装,
2 | 前身为EWebVeiw2模块,现时隔1年对其进行重写和加强。
3 |
4 | 作者QQ:2755482106(不闲聊)
5 | 交流用户群:372404087(付费50入群)
6 |
7 | 由原先的强制收费改为付费入群模式,
8 | 仅入群可查看使用手册及更多例程教程,
9 | 作者仅在EdgeView用户群提供技术支持。
10 |
11 | 如果你觉得付费入群免费使用的方式不能接受,
12 | 请立即删除本模块,喷子与狗不得使用。
13 |
14 | 免费发行包内仅包含核心模块和开发测试例程。
15 | 付费群内可下载多标签及其他例程,同时提供咨询服务。
16 |
17 | 如果感觉webview2的功能无法满足你,可以选择使用免费的ACF:
18 | 用户群:255175967
19 |
--------------------------------------------------------------------------------
/epltest/开发测试例.e:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Admenri/EdgeView/c556e12253ba1903dd9dca8b3993b34da2c7a33e/epltest/开发测试例.e
--------------------------------------------------------------------------------
/src/base/bind/callback.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
2 | // Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | /// \file
32 | /// A callback is similar in concept to a function pointer: it wraps a runnable
33 | /// object such as a function, method, lambda, or even another callback,
34 | /// allowing the runnable object to be invoked later via the callback object.
35 | ///
36 | /// Unlike function pointers, callbacks are created with base::BindOnce() or
37 | /// base::BindRepeating() and support partial function application.
38 | ///
39 | /// A base::OnceCallback may be Run() at most once; a base::RepeatingCallback
40 | /// may be Run() any number of times. |is_null()| is guaranteed to return true
41 | /// for a moved-from callback.
42 | ///
43 | ///
44 | /// // The lambda takes two arguments, but the first argument |x| is bound at
45 | /// // callback creation.
46 | /// base::OnceCallback cb = base::BindOnce([] (int x, int y) {
47 | /// return x + y;
48 | /// }, 1);
49 | /// // Run() only needs the remaining unbound argument |y|.
50 | /// printf("1 + 2 = %d\n", std::move(cb).Run(2)); // Prints 3
51 | /// printf("cb is null? %s\n",
52 | /// cb.is_null() ? "true" : "false"); // Prints true
53 | /// std::move(cb).Run(2); // Crashes since |cb| has already run.
54 | ///
55 | ///
56 | /// Callbacks also support cancellation. A common use is binding the receiver
57 | /// object as a WeakPtr. If that weak pointer is invalidated, calling Run()
58 | /// will be a no-op. Note that |IsCancelled()| and |is_null()| are distinct:
59 | /// simply cancelling a callback will not also make it null.
60 | ///
61 | /// See https://chromium.googlesource.com/chromium/src/+/lkgr/docs/callback.md
62 | /// for the full documentation.
63 |
64 | #ifndef BASE_BIND_CALLBACK_H_
65 | #define BASE_BIND_CALLBACK_H_
66 |
67 | // The following is substantially similar to the Chromium implementation.
68 | // If the Chromium implementation diverges the below implementation should be
69 | // updated to match.
70 |
71 | #include
72 |
73 | #include "base/bind/bind.h"
74 | #include "base/bind/callback_forward.h"
75 | #include "base/bind/callback_internal.h"
76 | #include "base/debug/logging.h"
77 |
78 | namespace base {
79 |
80 | template
81 | class OnceCallback : public internal::CallbackBase {
82 | public:
83 | using ResultType = R;
84 | using RunType = R(Args...);
85 | using PolymorphicInvoke = R (*)(internal::BindStateBase*,
86 | internal::PassingType...);
87 |
88 | constexpr OnceCallback() = default;
89 | OnceCallback(std::nullptr_t) = delete;
90 |
91 | explicit OnceCallback(internal::BindStateBase* bind_state)
92 | : internal::CallbackBase(bind_state) {}
93 |
94 | OnceCallback(const OnceCallback&) = delete;
95 | OnceCallback& operator=(const OnceCallback&) = delete;
96 |
97 | OnceCallback(OnceCallback&&) noexcept = default;
98 | OnceCallback& operator=(OnceCallback&&) noexcept = default;
99 |
100 | OnceCallback(RepeatingCallback other)
101 | : internal::CallbackBase(std::move(other)) {}
102 |
103 | OnceCallback& operator=(RepeatingCallback other) {
104 | static_cast(*this) = std::move(other);
105 | return *this;
106 | }
107 |
108 | R Run(Args... args) const& {
109 | static_assert(!sizeof(*this),
110 | "OnceCallback::Run() may only be invoked on a non-const "
111 | "rvalue, i.e. std::move(callback).Run().");
112 | NOTREACHED();
113 | }
114 |
115 | R Run(Args... args) && {
116 | // Move the callback instance into a local variable before the invocation,
117 | // that ensures the internal state is cleared after the invocation.
118 | // It's not safe to touch |this| after the invocation, since running the
119 | // bound function may destroy |this|.
120 | OnceCallback cb = std::move(*this);
121 | PolymorphicInvoke f =
122 | reinterpret_cast(cb.polymorphic_invoke());
123 | return f(cb.bind_state_.get(), std::forward(args)...);
124 | }
125 |
126 | // Then() returns a new OnceCallback that receives the same arguments as
127 | // |this|, and with the return type of |then|. The returned callback will:
128 | // 1) Run the functor currently bound to |this| callback.
129 | // 2) Run the |then| callback with the result from step 1 as its single
130 | // argument.
131 | // 3) Return the value from running the |then| callback.
132 | //
133 | // Since this method generates a callback that is a replacement for `this`,
134 | // `this` will be consumed and reset to a null callback to ensure the
135 | // originally-bound functor can be run at most once.
136 | template
137 | OnceCallback Then(OnceCallback then) && {
138 | CHECK(then);
139 | return BindOnce(
140 | internal::ThenHelper<
141 | OnceCallback, OnceCallback>::CreateTrampoline(),
142 | std::move(*this), std::move(then));
143 | }
144 |
145 | // This overload is required; even though RepeatingCallback is implicitly
146 | // convertible to OnceCallback, that conversion will not used when matching
147 | // for template argument deduction.
148 | template
149 | OnceCallback Then(
150 | RepeatingCallback then) && {
151 | CHECK(then);
152 | return BindOnce(
153 | internal::ThenHelper<
154 | OnceCallback,
155 | RepeatingCallback>::CreateTrampoline(),
156 | std::move(*this), std::move(then));
157 | }
158 | };
159 |
160 | template
161 | class RepeatingCallback : public internal::CallbackBaseCopyable {
162 | public:
163 | using ResultType = R;
164 | using RunType = R(Args...);
165 | using PolymorphicInvoke = R (*)(internal::BindStateBase*,
166 | internal::PassingType...);
167 |
168 | constexpr RepeatingCallback() = default;
169 | RepeatingCallback(std::nullptr_t) = delete;
170 |
171 | explicit RepeatingCallback(internal::BindStateBase* bind_state)
172 | : internal::CallbackBaseCopyable(bind_state) {}
173 |
174 | // Copyable and movable.
175 | RepeatingCallback(const RepeatingCallback&) = default;
176 | RepeatingCallback& operator=(const RepeatingCallback&) = default;
177 | RepeatingCallback(RepeatingCallback&&) noexcept = default;
178 | RepeatingCallback& operator=(RepeatingCallback&&) noexcept = default;
179 |
180 | bool operator==(const RepeatingCallback& other) const {
181 | return EqualsInternal(other);
182 | }
183 |
184 | bool operator!=(const RepeatingCallback& other) const {
185 | return !operator==(other);
186 | }
187 |
188 | R Run(Args... args) const& {
189 | PolymorphicInvoke f =
190 | reinterpret_cast(this->polymorphic_invoke());
191 | return f(this->bind_state_.get(), std::forward(args)...);
192 | }
193 |
194 | R Run(Args... args) && {
195 | // Move the callback instance into a local variable before the invocation,
196 | // that ensures the internal state is cleared after the invocation.
197 | // It's not safe to touch |this| after the invocation, since running the
198 | // bound function may destroy |this|.
199 | RepeatingCallback cb = std::move(*this);
200 | PolymorphicInvoke f =
201 | reinterpret_cast(cb.polymorphic_invoke());
202 | return f(std::move(cb).bind_state_.get(), std::forward(args)...);
203 | }
204 |
205 | // Then() returns a new RepeatingCallback that receives the same arguments as
206 | // |this|, and with the return type of |then|. The
207 | // returned callback will:
208 | // 1) Run the functor currently bound to |this| callback.
209 | // 2) Run the |then| callback with the result from step 1 as its single
210 | // argument.
211 | // 3) Return the value from running the |then| callback.
212 | //
213 | // If called on an rvalue (e.g. std::move(cb).Then(...)), this method
214 | // generates a callback that is a replacement for `this`. Therefore, `this`
215 | // will be consumed and reset to a null callback to ensure the
216 | // originally-bound functor will be run at most once.
217 | template
218 | RepeatingCallback Then(
219 | RepeatingCallback then) const& {
220 | CHECK(then);
221 | return BindRepeating(
222 | internal::ThenHelper<
223 | RepeatingCallback,
224 | RepeatingCallback>::CreateTrampoline(),
225 | *this, std::move(then));
226 | }
227 |
228 | template
229 | RepeatingCallback Then(
230 | RepeatingCallback then) && {
231 | CHECK(then);
232 | return BindRepeating(
233 | internal::ThenHelper<
234 | RepeatingCallback,
235 | RepeatingCallback>::CreateTrampoline(),
236 | std::move(*this), std::move(then));
237 | }
238 | };
239 |
240 | } // namespace base
241 |
242 | #endif // BASE_BIND_CALLBACK_H_
243 |
--------------------------------------------------------------------------------
/src/base/bind/callback_forward.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
2 | // Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | #ifndef BASE_BIND_CALLBACK_FORWARD_H_
32 | #define BASE_BIND_CALLBACK_FORWARD_H_
33 |
34 | // The following is substantially similar to the Chromium implementation.
35 | // If the Chromium implementation diverges the below implementation should be
36 | // updated to match.
37 |
38 | namespace base {
39 |
40 | template
41 | class OnceCallback;
42 |
43 | template
44 | class RepeatingCallback;
45 |
46 | ///
47 | /// Syntactic sugar to make OnceClosure and RepeatingClosure
48 | /// easier to declare since they will be used in a lot of APIs with delayed
49 | /// execution.
50 | ///
51 | using OnceClosure = OnceCallback;
52 | using RepeatingClosure = RepeatingCallback;
53 |
54 | } // namespace base
55 |
56 | #endif // BASE_BIND_CALLBACK_FORWARD_H_
57 |
--------------------------------------------------------------------------------
/src/base/bind/callback_helpers.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "base/bind/callback_helpers.h"
6 |
7 | namespace base {
8 |
9 | ScopedClosureRunner::ScopedClosureRunner() = default;
10 |
11 | ScopedClosureRunner::ScopedClosureRunner(OnceClosure closure)
12 | : closure_(std::move(closure)) {}
13 |
14 | ScopedClosureRunner::ScopedClosureRunner(ScopedClosureRunner&& other)
15 | : closure_(other.Release()) {}
16 |
17 | ScopedClosureRunner& ScopedClosureRunner::operator=(
18 | ScopedClosureRunner&& other) {
19 | if (this != &other) {
20 | RunAndReset();
21 | ReplaceClosure(other.Release());
22 | }
23 | return *this;
24 | }
25 |
26 | ScopedClosureRunner::~ScopedClosureRunner() { RunAndReset(); }
27 |
28 | void ScopedClosureRunner::RunAndReset() {
29 | if (closure_) {
30 | std::move(closure_).Run();
31 | }
32 | }
33 |
34 | void ScopedClosureRunner::ReplaceClosure(OnceClosure closure) {
35 | closure_ = std::move(closure);
36 | }
37 |
38 | OnceClosure ScopedClosureRunner::Release() { return std::move(closure_); }
39 |
40 | } // namespace base
41 |
--------------------------------------------------------------------------------
/src/base/bind/callback_helpers.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
2 | // Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | // This defines helpful methods for dealing with Callbacks. Because Callbacks
32 | // are implemented using templates, with a class per callback signature, adding
33 | // methods to Callback<> itself is unattractive (lots of extra code gets
34 | // generated). Instead, consider adding methods here.
35 |
36 | #ifndef BASE_BIND_CALLBACK_HELPERS_H_
37 | #define BASE_BIND_CALLBACK_HELPERS_H_
38 |
39 | // The following is substantially similar to the Chromium implementation.
40 | // If the Chromium implementation diverges the below implementation should be
41 | // updated to match.
42 |
43 | #include
44 | #include
45 | #include
46 | #include
47 |
48 | #include "base/bind/bind.h"
49 | #include "base/bind/callback.h"
50 | #include "base/debug/logging.h"
51 |
52 | namespace base {
53 |
54 | namespace internal {
55 |
56 | template
57 | struct IsBaseCallbackImpl : std::false_type {};
58 |
59 | template
60 | struct IsBaseCallbackImpl> : std::true_type {};
61 |
62 | template
63 | struct IsBaseCallbackImpl> : std::true_type {};
64 |
65 | template
66 | struct IsOnceCallbackImpl : std::false_type {};
67 |
68 | template
69 | struct IsOnceCallbackImpl> : std::true_type {};
70 |
71 | } // namespace internal
72 |
73 | ///
74 | /// IsBaseCallback::value is true when T is any of the Closure or Callback
75 | /// family of types.
76 | ///
77 | template
78 | using IsBaseCallback = internal::IsBaseCallbackImpl>;
79 |
80 | ///
81 | /// IsOnceCallback::value is true when T is a OnceClosure or OnceCallback
82 | /// type.
83 | ///
84 | template
85 | using IsOnceCallback = internal::IsOnceCallbackImpl>;
86 |
87 | ///
88 | /// SFINAE friendly enabler allowing to overload methods for both Repeating and
89 | /// OnceCallbacks.
90 | ///
91 | /// Usage:
92 | ///
93 | /// template class CallbackType,
94 | /// ... other template args ...,
95 | /// typename = EnableIfIsBaseCallback>
96 | /// void DoStuff(CallbackType<...> cb, ...);
97 | ///
98 | ///
99 | template class CallbackType>
100 | using EnableIfIsBaseCallback =
101 | std::enable_if_t>::value>;
102 |
103 | namespace internal {
104 |
105 | template
106 | class OnceCallbackHolder final {
107 | public:
108 | OnceCallbackHolder(OnceCallback callback,
109 | bool ignore_extra_runs)
110 | : callback_(std::move(callback)), ignore_extra_runs_(ignore_extra_runs) {
111 | DCHECK(callback_);
112 | }
113 | OnceCallbackHolder(const OnceCallbackHolder&) = delete;
114 | OnceCallbackHolder& operator=(const OnceCallbackHolder&) = delete;
115 |
116 | void Run(Args... args) {
117 | if (has_run_.exchange(true)) {
118 | CHECK(ignore_extra_runs_) << "Both OnceCallbacks returned by "
119 | "base::SplitOnceCallback() were run. "
120 | "At most one of the pair should be run.";
121 | return;
122 | }
123 | DCHECK(callback_);
124 | std::move(callback_).Run(std::forward(args)...);
125 | }
126 |
127 | private:
128 | volatile std::atomic_bool has_run_{false};
129 | base::OnceCallback callback_;
130 | const bool ignore_extra_runs_;
131 | };
132 |
133 | } // namespace internal
134 |
135 | ///
136 | /// Wraps the given OnceCallback into a RepeatingCallback that relays its
137 | /// invocation to the original OnceCallback on the first invocation. The
138 | /// following invocations are just ignored.
139 | ///
140 | /// Note that this deliberately subverts the Once/Repeating paradigm of
141 | /// Callbacks but helps ease the migration from old-style Callbacks. Avoid if
142 | /// possible; use if necessary for migration.
143 | ///
144 | // TODO(tzik): Remove it. https://crbug.com/730593
145 | template
146 | RepeatingCallback AdaptCallbackForRepeating(
147 | OnceCallback callback) {
148 | using Helper = internal::OnceCallbackHolder;
149 | return base::BindRepeating(
150 | &Helper::Run, std::make_unique(std::move(callback),
151 | /*ignore_extra_runs=*/true));
152 | }
153 |
154 | ///
155 | /// Wraps the given OnceCallback and returns two OnceCallbacks with an identical
156 | /// signature. On first invokation of either returned callbacks, the original
157 | /// callback is invoked. Invoking the remaining callback results in a crash.
158 | ///
159 | template
160 | std::pair, OnceCallback>
161 | SplitOnceCallback(OnceCallback callback) {
162 | using Helper = internal::OnceCallbackHolder;
163 | auto wrapped_once = base::BindRepeating(
164 | &Helper::Run, std::make_unique(std::move(callback),
165 | /*ignore_extra_runs=*/false));
166 | return std::make_pair(wrapped_once, wrapped_once);
167 | }
168 |
169 | ///
170 | /// ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
171 | /// that the Closure is executed no matter how the current scope exits.
172 | /// If you are looking for "ScopedCallback", "CallbackRunner", or
173 | /// "CallbackScoper" this is the class you want.
174 | ///
175 | class ScopedClosureRunner {
176 | public:
177 | ScopedClosureRunner();
178 | explicit ScopedClosureRunner(OnceClosure closure);
179 | ScopedClosureRunner(ScopedClosureRunner&& other);
180 | // Runs the current closure if it's set, then replaces it with the closure
181 | // from |other|. This is akin to how unique_ptr frees the contained pointer in
182 | // its move assignment operator. If you need to explicitly avoid running any
183 | // current closure, use ReplaceClosure().
184 | ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
185 | ~ScopedClosureRunner();
186 |
187 | explicit operator bool() const { return !!closure_; }
188 |
189 | // Calls the current closure and resets it, so it wont be called again.
190 | void RunAndReset();
191 |
192 | // Replaces closure with the new one releasing the old one without calling it.
193 | void ReplaceClosure(OnceClosure closure);
194 |
195 | // Releases the Closure without calling.
196 | [[nodiscard]] OnceClosure Release();
197 |
198 | private:
199 | OnceClosure closure_;
200 | };
201 |
202 | ///
203 | /// Creates a null callback.
204 | ///
205 | class NullCallback {
206 | public:
207 | template
208 | operator RepeatingCallback() const {
209 | return RepeatingCallback();
210 | }
211 | template
212 | operator OnceCallback() const {
213 | return OnceCallback();
214 | }
215 | };
216 |
217 | ///
218 | /// Creates a callback that does nothing when called.
219 | ///
220 | class DoNothing {
221 | public:
222 | template
223 | operator RepeatingCallback() const {
224 | return Repeatedly();
225 | }
226 | template
227 | operator OnceCallback() const {
228 | return Once();
229 | }
230 | // Explicit way of specifying a specific callback type when the compiler can't
231 | // deduce it.
232 | template
233 | static RepeatingCallback Repeatedly() {
234 | return BindRepeating([](Args... args) {});
235 | }
236 | template
237 | static OnceCallback Once() {
238 | return BindOnce([](Args... args) {});
239 | }
240 | };
241 |
242 | ///
243 | /// Useful for creating a Closure that will delete a pointer when invoked. Only
244 | /// use this when necessary. In most cases MessageLoop::DeleteSoon() is a better
245 | /// fit.
246 | ///
247 | template
248 | void DeletePointer(T* obj) {
249 | delete obj;
250 | }
251 |
252 | } // namespace base
253 |
254 | #endif // BASE_BIND_CALLBACK_HELPERS_H_
255 |
--------------------------------------------------------------------------------
/src/base/bind/callback_internal.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "base/bind/callback_internal.h"
6 |
7 | #include "base/debug/logging.h"
8 |
9 | namespace base {
10 | namespace internal {
11 |
12 | namespace {
13 |
14 | bool QueryCancellationTraitsForNonCancellables(
15 | const BindStateBase*, BindStateBase::CancellationQueryMode mode) {
16 | switch (mode) {
17 | case BindStateBase::IS_CANCELLED:
18 | return false;
19 | case BindStateBase::MAYBE_VALID:
20 | return true;
21 | }
22 | DCHECK(false);
23 | return false;
24 | }
25 |
26 | } // namespace
27 |
28 | void BindStateBaseRefCountTraits::Destruct(const BindStateBase* bind_state) {
29 | bind_state->destructor_(bind_state);
30 | }
31 |
32 | BindStateBase::BindStateBase(InvokeFuncStorage polymorphic_invoke,
33 | void (*destructor)(const BindStateBase*))
34 | : BindStateBase(polymorphic_invoke, destructor,
35 | &QueryCancellationTraitsForNonCancellables) {}
36 |
37 | BindStateBase::BindStateBase(InvokeFuncStorage polymorphic_invoke,
38 | void (*destructor)(const BindStateBase*),
39 | bool (*query_cancellation_traits)(
40 | const BindStateBase*, CancellationQueryMode))
41 | : polymorphic_invoke_(polymorphic_invoke),
42 | destructor_(destructor),
43 | query_cancellation_traits_(query_cancellation_traits) {}
44 |
45 | CallbackBase& CallbackBase::operator=(CallbackBase&& c) noexcept = default;
46 | CallbackBase::CallbackBase(const CallbackBaseCopyable& c)
47 | : bind_state_(c.bind_state_) {}
48 |
49 | CallbackBase& CallbackBase::operator=(const CallbackBaseCopyable& c) {
50 | bind_state_ = c.bind_state_;
51 | return *this;
52 | }
53 |
54 | CallbackBase::CallbackBase(CallbackBaseCopyable&& c) noexcept
55 | : bind_state_(std::move(c.bind_state_)) {}
56 |
57 | CallbackBase& CallbackBase::operator=(CallbackBaseCopyable&& c) noexcept {
58 | bind_state_ = std::move(c.bind_state_);
59 | return *this;
60 | }
61 |
62 | void CallbackBase::Reset() {
63 | // NULL the bind_state_ last, since it may be holding the last ref to whatever
64 | // object owns us, and we may be deleted after that.
65 | bind_state_ = nullptr;
66 | }
67 |
68 | bool CallbackBase::IsCancelled() const {
69 | DCHECK(bind_state_);
70 | return bind_state_->IsCancelled();
71 | }
72 |
73 | bool CallbackBase::MaybeValid() const {
74 | DCHECK(bind_state_);
75 | return bind_state_->MaybeValid();
76 | }
77 |
78 | bool CallbackBase::EqualsInternal(const CallbackBase& other) const {
79 | return bind_state_ == other.bind_state_;
80 | }
81 |
82 | CallbackBase::~CallbackBase() = default;
83 |
84 | CallbackBaseCopyable::CallbackBaseCopyable(const CallbackBaseCopyable& c) {
85 | bind_state_ = c.bind_state_;
86 | }
87 |
88 | CallbackBaseCopyable& CallbackBaseCopyable::operator=(
89 | const CallbackBaseCopyable& c) {
90 | bind_state_ = c.bind_state_;
91 | return *this;
92 | }
93 |
94 | CallbackBaseCopyable& CallbackBaseCopyable::operator=(
95 | CallbackBaseCopyable&& c) noexcept = default;
96 |
97 | } // namespace internal
98 | } // namespace base
99 |
--------------------------------------------------------------------------------
/src/base/bind/callback_internal.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 Google Inc. All rights reserved.
2 | //
3 | // Redistribution and use in source and binary forms, with or without
4 | // modification, are permitted provided that the following conditions are
5 | // met:
6 | //
7 | // * Redistributions of source code must retain the above copyright
8 | // notice, this list of conditions and the following disclaimer.
9 | // * Redistributions in binary form must reproduce the above
10 | // copyright notice, this list of conditions and the following disclaimer
11 | // in the documentation and/or other materials provided with the
12 | // distribution.
13 | // * Neither the name of Google Inc. nor the name Chromium Embedded
14 | // Framework nor the names of its contributors may be used to endorse
15 | // or promote products derived from this software without specific prior
16 | // written permission.
17 | //
18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 | // Do not include this header file directly. Use base/bind/bind.h or
31 | // base/bind/callback.h instead.
32 |
33 | // This file contains utility functions and classes that help the
34 | // implementation, and management of the Callback objects.
35 |
36 | #ifndef BASE_BIND_CALLBACK_INTERNAL_H_
37 | #define BASE_BIND_CALLBACK_INTERNAL_H_
38 |
39 | #include "base/bind/callback_forward.h"
40 | #include "base/memory/ref_counted.h"
41 |
42 | namespace base {
43 |
44 | struct FakeBindState;
45 |
46 | namespace internal {
47 |
48 | class BindStateBase;
49 | class FinallyExecutorCommon;
50 | class ThenAndCatchExecutorCommon;
51 |
52 | template
53 | class PostTaskExecutor;
54 |
55 | template
56 | struct BindState;
57 |
58 | class CallbackBase;
59 | class CallbackBaseCopyable;
60 |
61 | struct BindStateBaseRefCountTraits {
62 | static void Destruct(const BindStateBase*);
63 | };
64 |
65 | template
66 | using PassingType = std::conditional_t::value, T, T&&>;
67 |
68 | // BindStateBase is used to provide an opaque handle that the Callback
69 | // class can use to represent a function object with bound arguments. It
70 | // behaves as an existential type that is used by a corresponding
71 | // DoInvoke function to perform the function execution. This allows
72 | // us to shield the Callback class from the types of the bound argument via
73 | // "type erasure."
74 | // At the base level, the only task is to add reference counting data. Avoid
75 | // using or inheriting any virtual functions. Creating a vtable for every
76 | // BindState template instantiation results in a lot of bloat. Its only task is
77 | // to call the destructor which can be done with a function pointer.
78 | class BindStateBase
79 | : public RefCountedThreadSafe {
80 | public:
81 | REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
82 |
83 | enum CancellationQueryMode {
84 | IS_CANCELLED,
85 | MAYBE_VALID,
86 | };
87 |
88 | using InvokeFuncStorage = void (*)();
89 |
90 | BindStateBase(const BindStateBase&) = delete;
91 | BindStateBase& operator=(const BindStateBase&) = delete;
92 |
93 | private:
94 | BindStateBase(InvokeFuncStorage polymorphic_invoke,
95 | void (*destructor)(const BindStateBase*));
96 | BindStateBase(InvokeFuncStorage polymorphic_invoke,
97 | void (*destructor)(const BindStateBase*),
98 | bool (*query_cancellation_traits)(const BindStateBase*,
99 | CancellationQueryMode mode));
100 |
101 | ~BindStateBase() = default;
102 |
103 | friend struct BindStateBaseRefCountTraits;
104 | friend class RefCountedThreadSafe;
105 |
106 | friend class CallbackBase;
107 | friend class CallbackBaseCopyable;
108 |
109 | // Allowlist subclasses that access the destructor of BindStateBase.
110 | template
111 | friend struct BindState;
112 | friend struct ::base::FakeBindState;
113 |
114 | bool IsCancelled() const {
115 | return query_cancellation_traits_(this, IS_CANCELLED);
116 | }
117 |
118 | bool MaybeValid() const {
119 | return query_cancellation_traits_(this, MAYBE_VALID);
120 | }
121 |
122 | // In C++, it is safe to cast function pointers to function pointers of
123 | // another type. It is not okay to use void*. We create a InvokeFuncStorage
124 | // that that can store our function pointer, and then cast it back to
125 | // the original type on usage.
126 | InvokeFuncStorage polymorphic_invoke_;
127 |
128 | // Pointer to a function that will properly destroy |this|.
129 | void (*destructor_)(const BindStateBase*);
130 | bool (*query_cancellation_traits_)(const BindStateBase*,
131 | CancellationQueryMode mode);
132 | };
133 |
134 | // Holds the Callback methods that don't require specialization to reduce
135 | // template bloat.
136 | // CallbackBase is a direct base class of MoveOnly callbacks, and
137 | // CallbackBase uses CallbackBase for its implementation.
138 | class CallbackBase {
139 | public:
140 | inline CallbackBase(CallbackBase&& c) noexcept;
141 | CallbackBase& operator=(CallbackBase&& c) noexcept;
142 |
143 | explicit CallbackBase(const CallbackBaseCopyable& c);
144 | CallbackBase& operator=(const CallbackBaseCopyable& c);
145 |
146 | explicit CallbackBase(CallbackBaseCopyable&& c) noexcept;
147 | CallbackBase& operator=(CallbackBaseCopyable&& c) noexcept;
148 |
149 | // Returns true if Callback is null (doesn't refer to anything).
150 | bool is_null() const { return !bind_state_; }
151 | explicit operator bool() const { return !is_null(); }
152 |
153 | // Returns true if the callback invocation will be nop due to an cancellation.
154 | // It's invalid to call this on uninitialized callback.
155 | //
156 | // Must be called on the Callback's destination sequence.
157 | bool IsCancelled() const;
158 |
159 | // If this returns false, the callback invocation will be a nop due to a
160 | // cancellation. This may(!) still return true, even on a cancelled callback.
161 | //
162 | // This function is thread-safe.
163 | bool MaybeValid() const;
164 |
165 | // Returns the Callback into an uninitialized state.
166 | void Reset();
167 |
168 | protected:
169 | friend class FinallyExecutorCommon;
170 | friend class ThenAndCatchExecutorCommon;
171 |
172 | template
173 | friend class PostTaskExecutor;
174 |
175 | using InvokeFuncStorage = BindStateBase::InvokeFuncStorage;
176 |
177 | // Returns true if this callback equals |other|. |other| may be null.
178 | bool EqualsInternal(const CallbackBase& other) const;
179 |
180 | constexpr inline CallbackBase();
181 |
182 | // Allow initializing of |bind_state_| via the constructor to avoid default
183 | // initialization of the scoped_refptr.
184 | explicit inline CallbackBase(BindStateBase* bind_state);
185 |
186 | InvokeFuncStorage polymorphic_invoke() const {
187 | return bind_state_->polymorphic_invoke_;
188 | }
189 |
190 | // Force the destructor to be instantiated inside this translation unit so
191 | // that our subclasses will not get inlined versions. Avoids more template
192 | // bloat.
193 | ~CallbackBase();
194 |
195 | scoped_refptr bind_state_;
196 | };
197 |
198 | constexpr CallbackBase::CallbackBase() = default;
199 | CallbackBase::CallbackBase(CallbackBase&&) noexcept = default;
200 | CallbackBase::CallbackBase(BindStateBase* bind_state)
201 | : bind_state_(AdoptRef(bind_state)) {}
202 |
203 | // CallbackBase is a direct base class of Copyable Callbacks.
204 | class CallbackBaseCopyable : public CallbackBase {
205 | public:
206 | CallbackBaseCopyable(const CallbackBaseCopyable& c);
207 | CallbackBaseCopyable(CallbackBaseCopyable&& c) noexcept = default;
208 | CallbackBaseCopyable& operator=(const CallbackBaseCopyable& c);
209 | CallbackBaseCopyable& operator=(CallbackBaseCopyable&& c) noexcept;
210 |
211 | protected:
212 | constexpr CallbackBaseCopyable() = default;
213 | explicit CallbackBaseCopyable(BindStateBase* bind_state)
214 | : CallbackBase(bind_state) {}
215 | ~CallbackBaseCopyable() = default;
216 | };
217 |
218 | // Helpers for the `Then()` implementation.
219 | template
220 | struct ThenHelper;
221 |
222 | // Specialization when original callback returns `void`.
223 | template class OriginalCallback,
224 | template class ThenCallback, typename... OriginalArgs,
225 | typename ThenR, typename... ThenArgs>
226 | struct ThenHelper,
227 | ThenCallback> {
228 | static_assert(sizeof...(ThenArgs) == 0,
229 | "|then| callback cannot accept parameters if |this| has a "
230 | "void return type.");
231 |
232 | static auto CreateTrampoline() {
233 | return [](OriginalCallback c1,
234 | ThenCallback c2, OriginalArgs... c1_args) {
235 | std::move(c1).Run(std::forward(c1_args)...);
236 | return std::move(c2).Run();
237 | };
238 | }
239 | };
240 |
241 | // Specialization when original callback returns a non-void type.
242 | template class OriginalCallback,
243 | template class ThenCallback, typename OriginalR,
244 | typename... OriginalArgs, typename ThenR, typename... ThenArgs>
245 | struct ThenHelper,
246 | ThenCallback> {
247 | static_assert(sizeof...(ThenArgs) == 1,
248 | "|then| callback must accept exactly one parameter if |this| "
249 | "has a non-void return type.");
250 | // TODO(dcheng): This should probably check is_convertible as well (same with
251 | // `AssertBindArgsValidity`).
252 | static_assert(std::is_constructible::value,
253 | "|then| callback's parameter must be constructible from "
254 | "return type of |this|.");
255 |
256 | static auto CreateTrampoline() {
257 | return [](OriginalCallback c1,
258 | ThenCallback c2, OriginalArgs... c1_args) {
259 | return std::move(c2).Run(
260 | std::move(c1).Run(std::forward(c1_args)...));
261 | };
262 | }
263 | };
264 |
265 | } // namespace internal
266 | } // namespace base
267 |
268 | #endif // BASE_BIND_CALLBACK_INTERNAL_H_
269 |
--------------------------------------------------------------------------------
/src/base/bind/callback_list.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 The Chromium Authors
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "base/bind/callback_list.h"
6 |
7 | #include
8 |
9 | #include "base/bind/callback.h"
10 |
11 | namespace base {
12 |
13 | CallbackListSubscription::CallbackListSubscription() = default;
14 |
15 | CallbackListSubscription::CallbackListSubscription(base::OnceClosure closure)
16 | : closure_(std::move(closure)) {}
17 |
18 | CallbackListSubscription::CallbackListSubscription(
19 | CallbackListSubscription&& subscription)
20 | : closure_(std::move(subscription.closure_)) {}
21 |
22 | CallbackListSubscription& CallbackListSubscription::operator=(
23 | CallbackListSubscription&& subscription) {
24 | // Note: This still works properly for self-assignment.
25 | Run();
26 | closure_ = std::move(subscription.closure_);
27 | return *this;
28 | }
29 |
30 | CallbackListSubscription::~CallbackListSubscription() { Run(); }
31 |
32 | void CallbackListSubscription::Run() {
33 | if (closure_) std::move(closure_).Run();
34 | }
35 |
36 | } // namespace base
37 |
--------------------------------------------------------------------------------
/src/base/bind/cancelable_callback.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
2 | // Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | ///
32 | /// \file
33 | /// CancelableCallback is a wrapper around base::Callback that allows
34 | /// cancellation of a callback. CancelableCallback takes a reference on the
35 | /// wrapped callback until this object is destroyed or Reset()/Cancel() are
36 | /// called.
37 | ///
38 | /// NOTE:
39 | ///
40 | /// Calling CancelableCallback::Cancel() brings the object back to its natural,
41 | /// default-constructed state, i.e., CancelableCallback::callback() will return
42 | /// a null callback.
43 | ///
44 | /// THREAD-SAFETY:
45 | ///
46 | /// CancelableCallback objects must be created on, posted to, cancelled on, and
47 | /// destroyed on the same thread.
48 | ///
49 | ///
50 | /// EXAMPLE USAGE:
51 | ///
52 | /// In the following example, the test is verifying that RunIntensiveTest()
53 | /// Quit()s the message loop within 4 seconds. The cancelable callback is posted
54 | /// to the message loop, the intensive test runs, the message loop is run,
55 | /// then the callback is cancelled.
56 | ///
57 | ///
58 | /// RunLoop run_loop;
59 | ///
60 | /// void TimeoutCallback(const std::string& timeout_message) {
61 | /// FAIL() << timeout_message;
62 | /// run_loop.QuitWhenIdle();
63 | /// }
64 | ///
65 | /// CancelableOnceClosure timeout(
66 | /// base::BindOnce(&TimeoutCallback, "Test timed out."));
67 | /// ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE,
68 | /// timeout.callback(),
69 | /// TimeDelta::FromSeconds(4));
70 | /// RunIntensiveTest();
71 | /// run_loop.Run();
72 | /// // Hopefully this is hit before the timeout callback runs.
73 | /// timeout.Cancel();
74 | ///
75 | ///
76 |
77 | #ifndef BASE_BIND_CANCELABLE_CALLBACK_H_
78 | #define BASE_BIND_CANCELABLE_CALLBACK_H_
79 |
80 | // The following is substantially similar to the Chromium implementation.
81 | // If the Chromium implementation diverges the below implementation should be
82 | // updated to match.
83 |
84 | #include
85 |
86 | #include "base/bind/bind.h"
87 | #include "base/bind/callback.h"
88 | #include "base/bind/callback_internal.h"
89 | #include "base/buildflags/compiler_specific.h"
90 | #include "base/debug/logging.h"
91 | #include "base/memory/weak_ptr.h"
92 |
93 | namespace base {
94 | namespace internal {
95 |
96 | template
97 | class CancelableCallbackImpl {
98 | public:
99 | CancelableCallbackImpl() = default;
100 | CancelableCallbackImpl(const CancelableCallbackImpl&) = delete;
101 | CancelableCallbackImpl& operator=(const CancelableCallbackImpl&) = delete;
102 |
103 | // |callback| must not be null.
104 | explicit CancelableCallbackImpl(CallbackType callback)
105 | : callback_(std::move(callback)) {
106 | DCHECK(callback_);
107 | }
108 |
109 | ~CancelableCallbackImpl() = default;
110 |
111 | // Cancels and drops the reference to the wrapped callback.
112 | void Cancel() {
113 | weak_ptr_factory_.InvalidateWeakPtrs();
114 | callback_.Reset();
115 | }
116 |
117 | // Returns true if the wrapped callback has been cancelled.
118 | bool IsCancelled() const { return callback_.is_null(); }
119 |
120 | // Sets |callback| as the closure that may be cancelled. |callback| may not
121 | // be null. Outstanding and any previously wrapped callbacks are cancelled.
122 | void Reset(CallbackType callback) {
123 | DCHECK(callback);
124 | // Outstanding tasks (e.g., posted to a message loop) must not be called.
125 | Cancel();
126 | callback_ = std::move(callback);
127 | }
128 |
129 | // Returns a callback that can be disabled by calling Cancel().
130 | CallbackType callback() const {
131 | if (!callback_) {
132 | return CallbackType();
133 | }
134 | CallbackType forwarder;
135 | MakeForwarder(&forwarder);
136 | return forwarder;
137 | }
138 |
139 | private:
140 | template
141 | void MakeForwarder(RepeatingCallback* out) const {
142 | using ForwarderType = void (CancelableCallbackImpl::*)(Args...);
143 | ForwarderType forwarder = &CancelableCallbackImpl::ForwardRepeating;
144 | *out = BindRepeating(forwarder, weak_ptr_factory_.GetWeakPtr());
145 | }
146 |
147 | template
148 | void MakeForwarder(OnceCallback* out) const {
149 | using ForwarderType = void (CancelableCallbackImpl::*)(Args...);
150 | ForwarderType forwarder = &CancelableCallbackImpl::ForwardOnce;
151 | *out = BindOnce(forwarder, weak_ptr_factory_.GetWeakPtr());
152 | }
153 |
154 | template
155 | void ForwardRepeating(Args... args) {
156 | callback_.Run(std::forward(args)...);
157 | }
158 |
159 | template
160 | void ForwardOnce(Args... args) {
161 | weak_ptr_factory_.InvalidateWeakPtrs();
162 | std::move(callback_).Run(std::forward(args)...);
163 | }
164 |
165 | // The stored closure that may be cancelled.
166 | CallbackType callback_;
167 | mutable base::WeakPtrFactory weak_ptr_factory_{this};
168 | };
169 |
170 | } // namespace internal
171 |
172 | ///
173 | /// Consider using base::WeakPtr directly instead of base::CancelableCallback
174 | /// for the task cancellation.
175 | ///
176 | template
177 | using CancelableOnceCallback =
178 | internal::CancelableCallbackImpl>;
179 | using CancelableOnceClosure = CancelableOnceCallback;
180 |
181 | template
182 | using CancelableRepeatingCallback =
183 | internal::CancelableCallbackImpl>;
184 | using CancelableRepeatingClosure = CancelableRepeatingCallback;
185 |
186 | } // namespace base
187 |
188 | #endif // BASE_BIND_CANCELABLE_CALLBACK_H_
189 |
--------------------------------------------------------------------------------
/src/base/buildflags/build.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved.
2 | //
3 | // Redistribution and use in source and binary forms, with or without
4 | // modification, are permitted provided that the following conditions are
5 | // met:
6 | //
7 | // * Redistributions of source code must retain the above copyright
8 | // notice, this list of conditions and the following disclaimer.
9 | // * Redistributions in binary form must reproduce the above
10 | // copyright notice, this list of conditions and the following disclaimer
11 | // in the documentation and/or other materials provided with the
12 | // distribution.
13 | // * Neither the name of Google Inc. nor the name Chromium Embedded
14 | // Framework nor the names of its contributors may be used to endorse
15 | // or promote products derived from this software without specific prior
16 | // written permission.
17 | //
18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 | /// \file
31 | /// This file adds defines about the platform we're currently building on.
32 | ///
33 | ///
34 | /// Operating System:
35 | /// OS_AIX / OS_ANDROID / OS_ASMJS / OS_FREEBSD / OS_FUCHSIA / OS_IOS /
36 | /// OS_LINUX / OS_MAC / OS_NACL (SFI or NONSFI) / OS_NETBSD / OS_OPENBSD /
37 | /// OS_QNX / OS_SOLARIS / OS_WIN
38 | /// Operating System family:
39 | /// OS_APPLE: IOS or MAC
40 | /// OS_BSD: FREEBSD or NETBSD or OPENBSD
41 | /// OS_POSIX: AIX or ANDROID or ASMJS or CHROMEOS or FREEBSD or IOS or LINUX
42 | /// or MAC or NACL or NETBSD or OPENBSD or QNX or SOLARIS
43 | ///
44 | /// /!\ Note: OS_CHROMEOS is set by the build system, not this file
45 | ///
46 | /// Compiler:
47 | /// COMPILER_MSVC / COMPILER_GCC
48 | ///
49 | /// Processor:
50 | /// ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_MIPS / ARCH_CPU_MIPS64 /
51 | /// ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / ARCH_CPU_PPC64 / ARCH_CPU_S390 /
52 | /// ARCH_CPU_S390X / ARCH_CPU_X86 / ARCH_CPU_X86_64
53 | /// Processor family:
54 | /// ARCH_CPU_ARM_FAMILY: ARMEL or ARM64
55 | /// ARCH_CPU_MIPS_FAMILY: MIPS64EL or MIPSEL or MIPS64 or MIPS
56 | /// ARCH_CPU_PPC64_FAMILY: PPC64
57 | /// ARCH_CPU_S390_FAMILY: S390 or S390X
58 | /// ARCH_CPU_X86_FAMILY: X86 or X86_64
59 | /// Processor features:
60 | /// ARCH_CPU_31_BITS / ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
61 | /// ARCH_CPU_BIG_ENDIAN / ARCH_CPU_LITTLE_ENDIAN
62 | ///
63 | ///
64 |
65 | #ifndef BASE_BUILDFLAGS_BUILD_H_
66 | #define BASE_BUILDFLAGS_BUILD_H_
67 |
68 | // The following is substantially similar to the Chromium implementation.
69 | // If the Chromium implementation diverges the below implementation should be
70 | // updated to match.
71 |
72 | // A set of macros to use for platform detection.
73 | #if defined(ANDROID)
74 | #define OS_ANDROID 1
75 | #elif defined(__APPLE__)
76 | // Only include TargetConditionals after testing ANDROID as some Android builds
77 | // on the Mac have this header available and it's not needed unless the target
78 | // is really an Apple platform.
79 | #include
80 | #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
81 | #define OS_IOS 1
82 | #else
83 | #define OS_MAC 1
84 | // For backwards compatibility.
85 | #define OS_MACOSX 1
86 | #endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
87 | #elif defined(__linux__)
88 | #if !defined(OS_CHROMEOS)
89 | // Do not define OS_LINUX on Chrome OS build.
90 | // The OS_CHROMEOS macro is defined in GN.
91 | #define OS_LINUX 1
92 | #endif // !defined(OS_CHROMEOS)
93 | // Include a system header to pull in features.h for glibc/uclibc macros.
94 | #include
95 | #if defined(__GLIBC__) && !defined(__UCLIBC__)
96 | // We really are using glibc, not uClibc pretending to be glibc.
97 | #define LIBC_GLIBC 1
98 | #endif
99 | #elif defined(_WIN32)
100 | #define OS_WIN 1
101 | #elif defined(__Fuchsia__)
102 | #define OS_FUCHSIA 1
103 | #elif defined(__FreeBSD__)
104 | #define OS_FREEBSD 1
105 | #elif defined(__NetBSD__)
106 | #define OS_NETBSD 1
107 | #elif defined(__OpenBSD__)
108 | #define OS_OPENBSD 1
109 | #elif defined(__sun)
110 | #define OS_SOLARIS 1
111 | #elif defined(__QNXNTO__)
112 | #define OS_QNX 1
113 | #elif defined(_AIX)
114 | #define OS_AIX 1
115 | #elif defined(__asmjs__) || defined(__wasm__)
116 | #define OS_ASMJS 1
117 | #else
118 | #error Please add support for your platform in base/buildflags/build.h
119 | #endif
120 | // NOTE: Adding a new port? Please follow
121 | // https://chromium.googlesource.com/chromium/src/+/master/docs/new_port_policy.md
122 |
123 | #if defined(OS_MAC) || defined(OS_IOS)
124 | #define OS_APPLE 1
125 | #endif
126 |
127 | // For access to standard BSD features, use OS_BSD instead of a
128 | // more specific macro.
129 | #if defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD)
130 | #define OS_BSD 1
131 | #endif
132 |
133 | // For access to standard POSIXish features, use OS_POSIX instead of a
134 | // more specific macro.
135 | #if defined(OS_AIX) || defined(OS_ANDROID) || defined(OS_ASMJS) || \
136 | defined(OS_FREEBSD) || defined(OS_IOS) || defined(OS_LINUX) || \
137 | defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_NACL) || \
138 | defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_QNX) || \
139 | defined(OS_SOLARIS)
140 | #define OS_POSIX 1
141 | #endif
142 |
143 | // Compiler detection. Note: clang masquerades as GCC on POSIX and as MSVC on
144 | // Windows.
145 | #if defined(__GNUC__)
146 | #define COMPILER_GCC 1
147 | #elif defined(_MSC_VER)
148 | #define COMPILER_MSVC 1
149 | #else
150 | #error Please add support for your compiler in build/build_config.h
151 | #endif
152 |
153 | // Processor architecture detection. For more info on what's defined, see:
154 | // http://msdn.microsoft.com/en-us/library/b0084kay.aspx
155 | // http://www.agner.org/optimize/calling_conventions.pdf
156 | // or with gcc, run: "echo | gcc -E -dM -"
157 | #if defined(_M_X64) || defined(__x86_64__)
158 | #define ARCH_CPU_X86_FAMILY 1
159 | #define ARCH_CPU_X86_64 1
160 | #define ARCH_CPU_64_BITS 1
161 | #define ARCH_CPU_LITTLE_ENDIAN 1
162 | #elif defined(_M_IX86) || defined(__i386__)
163 | #define ARCH_CPU_X86_FAMILY 1
164 | #define ARCH_CPU_X86 1
165 | #define ARCH_CPU_32_BITS 1
166 | #define ARCH_CPU_LITTLE_ENDIAN 1
167 | #elif defined(__s390x__)
168 | #define ARCH_CPU_S390_FAMILY 1
169 | #define ARCH_CPU_S390X 1
170 | #define ARCH_CPU_64_BITS 1
171 | #define ARCH_CPU_BIG_ENDIAN 1
172 | #elif defined(__s390__)
173 | #define ARCH_CPU_S390_FAMILY 1
174 | #define ARCH_CPU_S390 1
175 | #define ARCH_CPU_31_BITS 1
176 | #define ARCH_CPU_BIG_ENDIAN 1
177 | #elif (defined(__PPC64__) || defined(__PPC__)) && defined(__BIG_ENDIAN__)
178 | #define ARCH_CPU_PPC64_FAMILY 1
179 | #define ARCH_CPU_PPC64 1
180 | #define ARCH_CPU_64_BITS 1
181 | #define ARCH_CPU_BIG_ENDIAN 1
182 | #elif defined(__PPC64__)
183 | #define ARCH_CPU_PPC64_FAMILY 1
184 | #define ARCH_CPU_PPC64 1
185 | #define ARCH_CPU_64_BITS 1
186 | #define ARCH_CPU_LITTLE_ENDIAN 1
187 | #elif defined(__ARMEL__)
188 | #define ARCH_CPU_ARM_FAMILY 1
189 | #define ARCH_CPU_ARMEL 1
190 | #define ARCH_CPU_32_BITS 1
191 | #define ARCH_CPU_LITTLE_ENDIAN 1
192 | #elif defined(__aarch64__) || defined(_M_ARM64)
193 | #define ARCH_CPU_ARM_FAMILY 1
194 | #define ARCH_CPU_ARM64 1
195 | #define ARCH_CPU_64_BITS 1
196 | #define ARCH_CPU_LITTLE_ENDIAN 1
197 | #elif defined(__pnacl__) || defined(__asmjs__) || defined(__wasm__)
198 | #define ARCH_CPU_32_BITS 1
199 | #define ARCH_CPU_LITTLE_ENDIAN 1
200 | #elif defined(__MIPSEL__)
201 | #if defined(__LP64__)
202 | #define ARCH_CPU_MIPS_FAMILY 1
203 | #define ARCH_CPU_MIPS64EL 1
204 | #define ARCH_CPU_64_BITS 1
205 | #define ARCH_CPU_LITTLE_ENDIAN 1
206 | #else
207 | #define ARCH_CPU_MIPS_FAMILY 1
208 | #define ARCH_CPU_MIPSEL 1
209 | #define ARCH_CPU_32_BITS 1
210 | #define ARCH_CPU_LITTLE_ENDIAN 1
211 | #endif
212 | #elif defined(__MIPSEB__)
213 | #if defined(__LP64__)
214 | #define ARCH_CPU_MIPS_FAMILY 1
215 | #define ARCH_CPU_MIPS64 1
216 | #define ARCH_CPU_64_BITS 1
217 | #define ARCH_CPU_BIG_ENDIAN 1
218 | #else
219 | #define ARCH_CPU_MIPS_FAMILY 1
220 | #define ARCH_CPU_MIPS 1
221 | #define ARCH_CPU_32_BITS 1
222 | #define ARCH_CPU_BIG_ENDIAN 1
223 | #endif
224 | #else
225 | #error Please add support for your architecture in base/buildflags/build.h
226 | #endif
227 |
228 | // Type detection for wchar_t.
229 | #if defined(OS_WIN)
230 | #define WCHAR_T_IS_UTF16
231 | #elif defined(OS_FUCHSIA)
232 | #define WCHAR_T_IS_UTF32
233 | #elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \
234 | (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
235 | #define WCHAR_T_IS_UTF32
236 | #elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \
237 | (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
238 | // On Posix, we'll detect short wchar_t, but projects aren't guaranteed to
239 | // compile in this mode (in particular, Chrome doesn't). This is intended for
240 | // other projects using base who manage their own dependencies and make sure
241 | // short wchar works for them.
242 | #define WCHAR_T_IS_UTF16
243 | #else
244 | #error Please add support for your compiler in base/buildflags/build.h
245 | #endif
246 |
247 | #if defined(OS_ANDROID)
248 | // The compiler thinks std::string::const_iterator and "const char*" are
249 | // equivalent types.
250 | #define STD_STRING_ITERATOR_IS_CHAR_POINTER
251 | // The compiler thinks std::u16string::const_iterator and "char16_t*" are
252 | // equivalent types.
253 | #define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER
254 | #endif
255 |
256 | #endif // BASE_BUILDFLAGS_BUILD_H_
257 |
--------------------------------------------------------------------------------
/src/base/debug/logging.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 The Chromium Embedded Framework Authors.
2 | // Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
3 | // Use of this source code is governed by a BSD-style license that can be
4 | // found in the LICENSE file.
5 |
6 | #include "base/debug/logging.h"
7 |
8 | #include
9 |
10 | #if defined(OS_WIN)
11 | #include
12 |
13 | #include
14 | #include
15 | #elif defined(OS_POSIX)
16 | #include
17 | #include
18 | #include
19 | #endif
20 |
21 | namespace base {
22 | namespace logging {
23 |
24 | namespace {
25 |
26 | #if defined(OS_POSIX)
27 | // From base/posix/safe_strerror.cc
28 |
29 | #if defined(__GLIBC__) || defined(OS_NACL)
30 | #define USE_HISTORICAL_STRERRO_R 1
31 | #else
32 | #define USE_HISTORICAL_STRERRO_R 0
33 | #endif
34 |
35 | #if USE_HISTORICAL_STRERRO_R && defined(__GNUC__)
36 | // GCC will complain about the unused second wrap function unless we tell it
37 | // that we meant for them to be potentially unused, which is exactly what this
38 | // attribute is for.
39 | #define POSSIBLY_UNUSED __attribute__((unused))
40 | #else
41 | #define POSSIBLY_UNUSED
42 | #endif
43 |
44 | #if USE_HISTORICAL_STRERRO_R
45 | // glibc has two strerror_r functions: a historical GNU-specific one that
46 | // returns type char *, and a POSIX.1-2001 compliant one available since 2.3.4
47 | // that returns int. This wraps the GNU-specific one.
48 | static void POSSIBLY_UNUSED
49 | wrap_posix_strerror_r(char* (*strerror_r_ptr)(int, char*, size_t), int err,
50 | char* buf, size_t len) {
51 | // GNU version.
52 | char* rc = (*strerror_r_ptr)(err, buf, len);
53 | if (rc != buf) {
54 | // glibc did not use buf and returned a static string instead. Copy it
55 | // into buf.
56 | buf[0] = '\0';
57 | strncat(buf, rc, len - 1);
58 | }
59 | // The GNU version never fails. Unknown errors get an "unknown error" message.
60 | // The result is always null terminated.
61 | }
62 | #endif // USE_HISTORICAL_STRERRO_R
63 |
64 | // Wrapper for strerror_r functions that implement the POSIX interface. POSIX
65 | // does not define the behaviour for some of the edge cases, so we wrap it to
66 | // guarantee that they are handled. This is compiled on all POSIX platforms, but
67 | // it will only be used on Linux if the POSIX strerror_r implementation is
68 | // being used (see below).
69 | static void POSSIBLY_UNUSED wrap_posix_strerror_r(
70 | int (*strerror_r_ptr)(int, char*, size_t), int err, char* buf, size_t len) {
71 | int old_errno = errno;
72 | // Have to cast since otherwise we get an error if this is the GNU version
73 | // (but in such a scenario this function is never called). Sadly we can't use
74 | // C++-style casts because the appropriate one is reinterpret_cast but it's
75 | // considered illegal to reinterpret_cast a type to itself, so we get an
76 | // error in the opposite case.
77 | int result = (*strerror_r_ptr)(err, buf, len);
78 | if (result == 0) {
79 | // POSIX is vague about whether the string will be terminated, although
80 | // it indirectly implies that typically ERANGE will be returned, instead
81 | // of truncating the string. We play it safe by always terminating the
82 | // string explicitly.
83 | buf[len - 1] = '\0';
84 | } else {
85 | // Error. POSIX is vague about whether the return value is itself a system
86 | // error code or something else. On Linux currently it is -1 and errno is
87 | // set. On BSD-derived systems it is a system error and errno is unchanged.
88 | // We try and detect which case it is so as to put as much useful info as
89 | // we can into our message.
90 | int strerror_error; // The error encountered in strerror
91 | int new_errno = errno;
92 | if (new_errno != old_errno) {
93 | // errno was changed, so probably the return value is just -1 or something
94 | // else that doesn't provide any info, and errno is the error.
95 | strerror_error = new_errno;
96 | } else {
97 | // Either the error from strerror_r was the same as the previous value, or
98 | // errno wasn't used. Assume the latter.
99 | strerror_error = result;
100 | }
101 | // snprintf truncates and always null-terminates.
102 | snprintf(buf, len, "Error %d while retrieving error %d", strerror_error,
103 | err);
104 | }
105 | errno = old_errno;
106 | }
107 |
108 | void safe_strerror_r(int err, char* buf, size_t len) {
109 | if (buf == NULL || len <= 0) {
110 | return;
111 | }
112 | // If using glibc (i.e., Linux), the compiler will automatically select the
113 | // appropriate overloaded function based on the function type of strerror_r.
114 | // The other one will be elided from the translation unit since both are
115 | // static.
116 | wrap_posix_strerror_r(&strerror_r, err, buf, len);
117 | }
118 |
119 | std::string safe_strerror(int err) {
120 | const int buffer_size = 256;
121 | char buf[buffer_size];
122 | safe_strerror_r(err, buf, sizeof(buf));
123 | return std::string(buf);
124 | }
125 | #endif // defined(OS_POSIX)
126 |
127 | } // namespace
128 |
129 | // MSVC doesn't like complex extern templates and DLLs.
130 | #if !defined(COMPILER_MSVC)
131 | // Explicit instantiations for commonly used comparisons.
132 | template std::string* MakeCheckOpString(const int&, const int&,
133 | const char* names);
134 | template std::string* MakeCheckOpString(
135 | const unsigned long&, const unsigned long&, const char* names);
136 | template std::string* MakeCheckOpString(
137 | const unsigned long&, const unsigned int&, const char* names);
138 | template std::string* MakeCheckOpString(
139 | const unsigned int&, const unsigned long&, const char* names);
140 | template std::string* MakeCheckOpString(
141 | const std::string&, const std::string&, const char* name);
142 | #endif
143 |
144 | #if defined(OS_WIN)
145 | LogMessage::SaveLastError::SaveLastError() : last_error_(::GetLastError()) {}
146 |
147 | LogMessage::SaveLastError::~SaveLastError() { ::SetLastError(last_error_); }
148 | #endif // defined(OS_WIN)
149 |
150 | LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
151 | : severity_(severity), file_(file), line_(line) {}
152 |
153 | LogMessage::LogMessage(const char* file, int line, std::string* result)
154 | : severity_(LOG_FATAL), file_(file), line_(line) {
155 | stream_ << "Check failed: " << *result;
156 | delete result;
157 | }
158 |
159 | LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
160 | std::string* result)
161 | : severity_(severity), file_(file), line_(line) {
162 | stream_ << "Check failed: " << *result;
163 | delete result;
164 | }
165 |
166 | LogMessage::~LogMessage() {
167 | std::string str_newline(stream_.str());
168 |
169 | if (severity_ >= LOG_ERROR) {
170 | std::cout << "[ELOG] File: " << file_ << "\nLine: " << line_
171 | << "\nLevel: " << severity_ << "\nInfo: " << str_newline << '\n';
172 | } else {
173 | std::cout << "[LOG] " << str_newline << '\n';
174 | }
175 | }
176 |
177 | #if defined(OS_WIN)
178 | // This has already been defined in the header, but defining it again as DWORD
179 | // ensures that the type used in the header is equivalent to DWORD. If not,
180 | // the redefinition is a compile error.
181 | using SystemErrorCode = DWORD;
182 | #endif
183 |
184 | SystemErrorCode GetLastSystemErrorCode() {
185 | #if defined(OS_WIN)
186 | return ::GetLastError();
187 | #elif defined(OS_POSIX)
188 | return errno;
189 | #else
190 | #error Not implemented
191 | #endif
192 | }
193 |
194 | #if defined(OS_WIN)
195 | std::string SystemErrorCodeToString(SystemErrorCode error_code) {
196 | const int error_message_buffer_size = 256;
197 | char msgbuf[error_message_buffer_size];
198 | DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
199 | DWORD len = FormatMessageA(flags, NULL, error_code, 0, msgbuf,
200 | static_cast(std::size(msgbuf)), NULL);
201 | std::stringstream ss;
202 | if (len) {
203 | std::string s(msgbuf);
204 | // Messages returned by system end with line breaks.
205 | s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
206 | ss << s << " (0x" << std::hex << error_code << ")";
207 | } else {
208 | ss << "Error (0x" << std::hex << GetLastError()
209 | << ") while retrieving error. (0x" << error_code << ")";
210 | }
211 | return ss.str();
212 | }
213 | #elif defined(OS_POSIX)
214 | std::string SystemErrorCodeToString(SystemErrorCode error_code) {
215 | return safe_strerror(error_code);
216 | }
217 | #else
218 | #error Not implemented
219 | #endif
220 |
221 | #if defined(OS_WIN)
222 | Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, int line,
223 | LogSeverity severity,
224 | SystemErrorCode err)
225 | : err_(err), log_message_(file, line, severity) {}
226 |
227 | Win32ErrorLogMessage::~Win32ErrorLogMessage() {
228 | stream() << ": " << SystemErrorCodeToString(err_);
229 | }
230 | #elif defined(OS_POSIX)
231 | ErrnoLogMessage::ErrnoLogMessage(const char* file, int line,
232 | LogSeverity severity, SystemErrorCode err)
233 | : err_(err), log_message_(file, line, severity) {}
234 |
235 | ErrnoLogMessage::~ErrnoLogMessage() {
236 | stream() << ": " << SystemErrorCodeToString(err_);
237 | }
238 | #endif // OS_WIN
239 |
240 | } // namespace logging
241 | } // namespace base
242 |
--------------------------------------------------------------------------------
/src/base/memory/atomic_flag.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "base/memory/atomic_flag.h"
6 |
7 | #include "base/debug/logging.h"
8 |
9 | namespace base {
10 |
11 | AtomicFlag::AtomicFlag() {
12 | // It doesn't matter where the AtomicFlag is built so long as it's always
13 | // Set() from the same sequence after. Note: the sequencing requirements are
14 | // necessary for IsSet()'s callers to know which sequence's memory operations
15 | // they are synchronized with.
16 | set_thread_checker_.DetachFromThread();
17 | }
18 |
19 | AtomicFlag::~AtomicFlag() = default;
20 |
21 | void AtomicFlag::Set() {
22 | DCHECK(set_thread_checker_.CalledOnValidThread());
23 | flag_.store(1, std::memory_order_release);
24 | }
25 |
26 | void AtomicFlag::UnsafeResetForTesting() {
27 | set_thread_checker_.DetachFromThread();
28 | flag_.store(0, std::memory_order_release);
29 | }
30 |
31 | } // namespace base
32 |
--------------------------------------------------------------------------------
/src/base/memory/atomic_flag.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
2 | // Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | #ifndef BASE_MEMORY_ATOMIC_FLAG_H_
32 | #define BASE_MEMORY_ATOMIC_FLAG_H_
33 |
34 | // The following is substantially similar to the Chromium implementation.
35 | // If the Chromium implementation diverges the below implementation should be
36 | // updated to match.
37 |
38 | #include
39 |
40 | #include
41 |
42 | #include "base/thread/thread_checker.h"
43 |
44 | namespace base {
45 |
46 | ///
47 | /// A flag that can safely be set from one thread and read from other threads.
48 | ///
49 | /// This class IS NOT intended for synchronization between threads.
50 | ///
51 | class AtomicFlag {
52 | public:
53 | AtomicFlag();
54 |
55 | AtomicFlag(const AtomicFlag&) = delete;
56 | AtomicFlag& operator=(const AtomicFlag&) = delete;
57 |
58 | ~AtomicFlag();
59 |
60 | ///
61 | /// Set the flag. Must always be called from the same thread.
62 | ///
63 | void Set();
64 |
65 | ///
66 | /// Returns true iff the flag was set. If this returns true, the current
67 | /// thread is guaranteed to be synchronized with all memory operations on the
68 | /// thread which invoked Set() up until at least the first call to Set() on
69 | /// it.
70 | ///
71 | bool IsSet() const {
72 | // Inline here: this has a measurable performance impact on base::WeakPtr.
73 | return flag_.load(std::memory_order_acquire) != 0;
74 | }
75 |
76 | ///
77 | /// Resets the flag. Be careful when using this: callers might not expect
78 | /// IsSet() to return false after returning true once.
79 | ///
80 | void UnsafeResetForTesting();
81 |
82 | private:
83 | std::atomic flag_{0};
84 | base::ThreadChecker set_thread_checker_;
85 | };
86 |
87 | } // namespace base
88 |
89 | #endif // BASE_MEMORY_ATOMIC_FLAG_H_
90 |
--------------------------------------------------------------------------------
/src/base/memory/atomic_ref_count.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
2 | // Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | // This is a low level implementation of atomic semantics for reference
32 | // counting. Please use ref_counted.h directly instead.
33 | //
34 | // The Chromium implementation includes annotations to avoid some false
35 | // positives when using data race detection tools. Annotations are not
36 | // currently supported by the self implementation.
37 |
38 | #ifndef BASE_MEMORY_ATOMIC_REF_COUNT_H_
39 | #define BASE_MEMORY_ATOMIC_REF_COUNT_H_
40 |
41 | // The following is substantially similar to the Chromium implementation.
42 | // If the Chromium implementation diverges the below implementation should be
43 | // updated to match.
44 |
45 | #include
46 |
47 | namespace base {
48 |
49 | class AtomicRefCount {
50 | public:
51 | constexpr AtomicRefCount() : ref_count_(0) {}
52 | explicit constexpr AtomicRefCount(int initial_value)
53 | : ref_count_(initial_value) {}
54 |
55 | ///
56 | /// Increment a reference count.
57 | /// Returns the previous value of the count.
58 | ///
59 | int Increment() { return Increment(1); }
60 |
61 | ///
62 | /// Increment a reference count by "increment", which must exceed 0.
63 | /// Returns the previous value of the count.
64 | ///
65 | int Increment(int increment) {
66 | return ref_count_.fetch_add(increment, std::memory_order_relaxed);
67 | }
68 |
69 | ///
70 | /// Decrement a reference count, and return whether the result is non-zero.
71 | /// Insert barriers to ensure that state written before the reference count
72 | /// became zero will be visible to a thread that has just made the count zero.
73 | ///
74 | bool Decrement() {
75 | // TODO(jbroman): Technically this doesn't need to be an acquire operation
76 | // unless the result is 1 (i.e., the ref count did indeed reach zero).
77 | // However, there are toolchain issues that make that not work as well at
78 | // present (notably TSAN doesn't like it).
79 | return ref_count_.fetch_sub(1, std::memory_order_acq_rel) != 1;
80 | }
81 |
82 | ///
83 | /// Return whether the reference count is one. If the reference count is used
84 | /// in the conventional way, a refrerence count of 1 implies that the current
85 | /// thread owns the reference and no other thread shares it. This call
86 | /// performs the test for a reference count of one, and performs the memory
87 | /// barrier needed for the owning thread to act on the object, knowing that it
88 | /// has exclusive access to the object.
89 | ///
90 | bool IsOne() const { return ref_count_.load(std::memory_order_acquire) == 1; }
91 |
92 | ///
93 | /// Return whether the reference count is zero. With conventional object
94 | /// referencing counting, the object will be destroyed, so the reference count
95 | /// should never be zero. Hence this is generally used for a debug check.
96 | ///
97 | bool IsZero() const {
98 | return ref_count_.load(std::memory_order_acquire) == 0;
99 | }
100 |
101 | ///
102 | /// Returns the current reference count (with no barriers). This is subtle,
103 | /// and should be used only for debugging.
104 | ///
105 | int SubtleRefCountForDebug() const {
106 | return ref_count_.load(std::memory_order_relaxed);
107 | }
108 |
109 | private:
110 | std::atomic_int ref_count_;
111 | };
112 |
113 | } // namespace base
114 |
115 | #endif // BASE_MEMORY_ATOMIC_REF_COUNT_H_
116 |
--------------------------------------------------------------------------------
/src/base/memory/auto_reset.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
2 | // Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | // base::AutoReset<> is useful for setting a variable to a new value only within
32 | // a particular scope. An base::AutoReset<> object resets a variable to its
33 | // original value upon destruction, making it an alternative to writing
34 | // "var = false;" or "var = old_val;" at all of a block's exit points.
35 | //
36 | // This should be obvious, but note that an base::AutoReset<> instance should
37 | // have a shorter lifetime than its scoped_variable, to prevent invalid memory
38 | // writes when the base::AutoReset<> object is destroyed.
39 |
40 | #ifndef BASE_MEMORY_AUTO_RESET_H_
41 | #define BASE_MEMORY_AUTO_RESET_H_
42 |
43 | // The following is substantially similar to the Chromium implementation.
44 | // If the Chromium implementation diverges the below implementation should be
45 | // updated to match.
46 |
47 | #include
48 |
49 | namespace base {
50 |
51 | template
52 | class AutoReset {
53 | public:
54 | template
55 | AutoReset(T* scoped_variable, U&& new_value)
56 | : scoped_variable_(scoped_variable),
57 | original_value_(
58 | std::exchange(*scoped_variable_, std::forward(new_value))) {}
59 |
60 | AutoReset(AutoReset&& other)
61 | : scoped_variable_(std::exchange(other.scoped_variable_, nullptr)),
62 | original_value_(std::move(other.original_value_)) {}
63 |
64 | AutoReset& operator=(AutoReset&& rhs) {
65 | scoped_variable_ = std::exchange(rhs.scoped_variable_, nullptr);
66 | original_value_ = std::move(rhs.original_value_);
67 | return *this;
68 | }
69 |
70 | ~AutoReset() {
71 | if (scoped_variable_) {
72 | *scoped_variable_ = std::move(original_value_);
73 | }
74 | }
75 |
76 | private:
77 | T* scoped_variable_;
78 | T original_value_;
79 | };
80 |
81 | } // namespace base
82 |
83 | #endif // BASE_MEMORY_AUTO_RESET_H_
84 |
--------------------------------------------------------------------------------
/src/base/memory/lock.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
2 | // Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | #ifndef BASE_MEMORY_LOCK_H_
32 | #define BASE_MEMORY_LOCK_H_
33 |
34 | // The following is substantially similar to the Chromium implementation.
35 | // If the Chromium implementation diverges the below implementation should be
36 | // updated to match.
37 |
38 | #include "base/debug/logging.h"
39 | #include "base/memory/lock_impl.h"
40 |
41 | namespace base {
42 | namespace internal {
43 |
44 | ///
45 | /// A convenient wrapper for an OS specific critical section. The only real
46 | /// intelligence in this class is in debug mode for the support for the
47 | /// AssertAcquired() method.
48 | ///
49 | class Lock {
50 | public:
51 | Lock() : lock_() {}
52 |
53 | Lock(const Lock&) = delete;
54 | Lock& operator=(const Lock&) = delete;
55 |
56 | ~Lock() {}
57 | void Acquire() { lock_.Lock(); }
58 | void Release() { lock_.Unlock(); }
59 |
60 | ///
61 | /// If the lock is not held, take it and return true. If the lock is already
62 | /// held by another thread, immediately return false. This must not be called
63 | /// by a thread already holding the lock (what happens is undefined and an
64 | /// assertion may fail).
65 | ///
66 | bool Try() { return lock_.Try(); }
67 |
68 | private:
69 | // Platform specific underlying lock implementation.
70 | LockImpl lock_;
71 | };
72 |
73 | ///
74 | /// A helper class that acquires the given Lock while the AutoLock is in scope.
75 | ///
76 | class AutoLock {
77 | public:
78 | struct AlreadyAcquired {};
79 |
80 | explicit AutoLock(Lock& lock) : lock_(lock) { lock_.Acquire(); }
81 |
82 | AutoLock(Lock& lock, const AlreadyAcquired&) : lock_(lock) {}
83 |
84 | AutoLock(const AutoLock&) = delete;
85 | AutoLock& operator=(const AutoLock&) = delete;
86 |
87 | ~AutoLock() { lock_.Release(); }
88 |
89 | private:
90 | Lock& lock_;
91 | };
92 |
93 | ///
94 | /// AutoUnlock is a helper that will Release() the |lock| argument in the
95 | /// constructor, and re-Acquire() it in the destructor.
96 | ///
97 | class AutoUnlock {
98 | public:
99 | explicit AutoUnlock(Lock& lock) : lock_(lock) {
100 | // We require our caller to have the lock.
101 | lock_.Release();
102 | }
103 |
104 | AutoUnlock(const AutoUnlock&) = delete;
105 | AutoUnlock& operator=(const AutoUnlock&) = delete;
106 |
107 | ~AutoUnlock() { lock_.Acquire(); }
108 |
109 | private:
110 | Lock& lock_;
111 | };
112 |
113 | } // namespace internal
114 |
115 | // Implement classes in the internal namespace and then expose them to the
116 | // base namespace. This avoids conflicts with the base.lib implementation when
117 | // linking sandbox support on Windows.
118 | using internal::AutoLock;
119 | using internal::AutoUnlock;
120 | using internal::Lock;
121 |
122 | } // namespace base
123 |
124 | #endif // BASE_MEMORY_LOCK_H_
125 |
--------------------------------------------------------------------------------
/src/base/memory/lock_impl.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "base/memory/lock_impl.h"
6 |
7 | #if defined(OS_WIN)
8 |
9 | namespace base {
10 | namespace internal {
11 |
12 | LockImpl::LockImpl() {
13 | // The second parameter is the spin count, for short-held locks it avoid the
14 | // contending thread from going to sleep which helps performance greatly.
15 | ::InitializeCriticalSectionAndSpinCount(&native_handle_, 2000);
16 | }
17 |
18 | LockImpl::~LockImpl() { ::DeleteCriticalSection(&native_handle_); }
19 |
20 | bool LockImpl::Try() {
21 | if (::TryEnterCriticalSection(&native_handle_) != FALSE) {
22 | return true;
23 | }
24 | return false;
25 | }
26 |
27 | void LockImpl::Lock() { ::EnterCriticalSection(&native_handle_); }
28 |
29 | void LockImpl::Unlock() { ::LeaveCriticalSection(&native_handle_); }
30 |
31 | } // namespace internal
32 | } // namespace base
33 |
34 | #elif defined(OS_POSIX)
35 |
36 | #include
37 | #include
38 |
39 | #include "base/debug/logging.h"
40 |
41 | namespace base {
42 | namespace internal {
43 |
44 | LockImpl::LockImpl() {
45 | #if DCHECK_IS_ON()
46 | // In debug, setup attributes for lock error checking.
47 | pthread_mutexattr_t mta;
48 | int rv = pthread_mutexattr_init(&mta);
49 | DCHECK_EQ(rv, 0) << ". " << strerror(rv);
50 | rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);
51 | DCHECK_EQ(rv, 0) << ". " << strerror(rv);
52 | rv = pthread_mutex_init(&native_handle_, &mta);
53 | DCHECK_EQ(rv, 0) << ". " << strerror(rv);
54 | rv = pthread_mutexattr_destroy(&mta);
55 | DCHECK_EQ(rv, 0) << ". " << strerror(rv);
56 | #else
57 | // In release, go with the default lock attributes.
58 | pthread_mutex_init(&native_handle_, NULL);
59 | #endif
60 | }
61 |
62 | LockImpl::~LockImpl() {
63 | int rv = pthread_mutex_destroy(&native_handle_);
64 | DCHECK_EQ(rv, 0) << ". " << strerror(rv);
65 | }
66 |
67 | bool LockImpl::Try() {
68 | int rv = pthread_mutex_trylock(&native_handle_);
69 | DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv);
70 | return rv == 0;
71 | }
72 |
73 | void LockImpl::Lock() {
74 | int rv = pthread_mutex_lock(&native_handle_);
75 | DCHECK_EQ(rv, 0) << ". " << strerror(rv);
76 | }
77 |
78 | void LockImpl::Unlock() {
79 | int rv = pthread_mutex_unlock(&native_handle_);
80 | DCHECK_EQ(rv, 0) << ". " << strerror(rv);
81 | }
82 |
83 | } // namespace internal
84 | } // namespace base
85 |
86 | #endif // defined(OS_POSIX)
87 |
--------------------------------------------------------------------------------
/src/base/memory/lock_impl.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2011 Google Inc. All rights reserved.
2 | //
3 | // Redistribution and use in source and binary forms, with or without
4 | // modification, are permitted provided that the following conditions are
5 | // met:
6 | //
7 | // * Redistributions of source code must retain the above copyright
8 | // notice, this list of conditions and the following disclaimer.
9 | // * Redistributions in binary form must reproduce the above
10 | // copyright notice, this list of conditions and the following disclaimer
11 | // in the documentation and/or other materials provided with the
12 | // distribution.
13 | // * Neither the name of Google Inc. nor the name Chromium Embedded
14 | // Framework nor the names of its contributors may be used to endorse
15 | // or promote products derived from this software without specific prior
16 | // written permission.
17 | //
18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 | #ifndef BASE_MEMORY_LOCK_IMPL_H_
31 | #define BASE_MEMORY_LOCK_IMPL_H_
32 |
33 | #include "base/buildflags/build.h"
34 |
35 | #if defined(OS_WIN)
36 | #include
37 | #elif defined(OS_POSIX)
38 | #include
39 | #endif
40 |
41 | namespace base {
42 | namespace internal {
43 |
44 | // This class implements the underlying platform-specific spin-lock mechanism
45 | // used for the Lock class. Most users should not use LockImpl directly, but
46 | // should instead use Lock.
47 | class LockImpl {
48 | public:
49 | #if defined(OS_WIN)
50 | typedef CRITICAL_SECTION NativeHandle;
51 | #elif defined(OS_POSIX)
52 | typedef pthread_mutex_t NativeHandle;
53 | #endif
54 |
55 | LockImpl();
56 |
57 | LockImpl(const LockImpl&) = delete;
58 | LockImpl& operator=(const LockImpl&) = delete;
59 |
60 | ~LockImpl();
61 |
62 | // If the lock is not held, take it and return true. If the lock is already
63 | // held by something else, immediately return false.
64 | bool Try();
65 |
66 | // Take the lock, blocking until it is available if necessary.
67 | void Lock();
68 |
69 | // Release the lock. This must only be called by the lock's holder: after
70 | // a successful call to Try, or a call to Lock.
71 | void Unlock();
72 |
73 | // Return the native underlying lock.
74 | // TODO(awalker): refactor lock and condition variables so that this is
75 | // unnecessary.
76 | NativeHandle* native_handle() { return &native_handle_; }
77 |
78 | private:
79 | NativeHandle native_handle_;
80 | };
81 |
82 | } // namespace internal
83 | } // namespace base
84 |
85 | #endif // BASE_MEMORY_LOCK_IMPL_H_
86 |
--------------------------------------------------------------------------------
/src/base/memory/raw_scoped_refptr_mismatch_checker.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2011 Google Inc. All rights reserved.
2 | //
3 | // Redistribution and use in source and binary forms, with or without
4 | // modification, are permitted provided that the following conditions are
5 | // met:
6 | //
7 | // * Redistributions of source code must retain the above copyright
8 | // notice, this list of conditions and the following disclaimer.
9 | // * Redistributions in binary form must reproduce the above
10 | // copyright notice, this list of conditions and the following disclaimer
11 | // in the documentation and/or other materials provided with the
12 | // distribution.
13 | // * Neither the name of Google Inc. nor the name Chromium Embedded
14 | // Framework nor the names of its contributors may be used to endorse
15 | // or promote products derived from this software without specific prior
16 | // written permission.
17 | //
18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 | // Do not include this header file directly. Use base/bind/callback.h instead.
31 |
32 | #ifndef BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
33 | #define BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
34 |
35 | #include
36 |
37 | #include "base/template_util.h"
38 |
39 | // It is dangerous to post a task with a T* argument where T is a subtype of
40 | // RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the
41 | // object may already have been deleted since it was not held with a
42 | // scoped_refptr. Example: http://crbug.com/27191
43 | // The following set of traits are designed to generate a compile error
44 | // whenever this antipattern is attempted.
45 |
46 | namespace base {
47 |
48 | // This is a base internal implementation file used by task.h and callback.h.
49 | // Not for public consumption, so we wrap it in namespace internal.
50 | namespace internal {
51 |
52 | template
53 | struct IsRefCountedType : std::false_type {};
54 |
55 | template
56 | struct IsRefCountedType()->AddRef()),
57 | decltype(std::declval()->Release())>>
58 | : std::true_type {};
59 |
60 | // Human readable translation: you needed to be a scoped_refptr if you are a raw
61 | // pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) type.
62 | template
63 | struct NeedsScopedRefptrButGetsRawPtr
64 | : conjunction,
65 | IsRefCountedType>> {
66 | static_assert(!std::is_reference::value,
67 | "NeedsScopedRefptrButGetsRawPtr requires non-reference type.");
68 | };
69 |
70 | } // namespace internal
71 |
72 | } // namespace base
73 |
74 | #endif // BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
75 |
--------------------------------------------------------------------------------
/src/base/memory/ref_counted.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "base/memory/ref_counted.h"
6 |
7 | #include
8 | #include
9 |
10 | namespace base {
11 | namespace {
12 |
13 | #if DCHECK_IS_ON()
14 | std::atomic_int g_cross_thread_ref_count_access_allow_count(0);
15 | #endif
16 |
17 | } // namespace
18 |
19 | namespace subtle {
20 |
21 | bool RefCountedThreadSafeBase::HasOneRef() const { return ref_count_.IsOne(); }
22 |
23 | bool RefCountedThreadSafeBase::HasAtLeastOneRef() const {
24 | return !ref_count_.IsZero();
25 | }
26 |
27 | #if DCHECK_IS_ON()
28 | RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
29 | DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
30 | "calling Release()";
31 | }
32 | #endif
33 |
34 | // For security and correctness, we check the arithmetic on ref counts.
35 | //
36 | // In an attempt to avoid binary bloat (from inlining the `CHECK`), we define
37 | // these functions out-of-line. However, compilers are wily. Further testing may
38 | // show that `NOINLINE` helps or hurts.
39 | //
40 | #if defined(ARCH_CPU_64_BITS)
41 | void RefCountedBase::AddRefImpl() const {
42 | // An attacker could induce use-after-free bugs, and potentially exploit them,
43 | // by creating so many references to a ref-counted object that the reference
44 | // count overflows. On 32-bit architectures, there is not enough address space
45 | // to succeed. But on 64-bit architectures, it might indeed be possible.
46 | // Therefore, we can elide the check for arithmetic overflow on 32-bit, but we
47 | // must check on 64-bit.
48 | //
49 | // Make sure the addition didn't wrap back around to 0. This form of check
50 | // works because we assert that `ref_count_` is an unsigned integer type.
51 | CHECK(++ref_count_ != 0);
52 | }
53 |
54 | void RefCountedBase::ReleaseImpl() const {
55 | // Make sure the subtraction didn't wrap back around from 0 to the max value.
56 | // That could cause memory leaks, and may induce application-semantic
57 | // correctness or safety bugs. (E.g. what if we really needed that object to
58 | // be destroyed at the right time?)
59 | //
60 | // Note that unlike with overflow, underflow could also happen on 32-bit
61 | // architectures. Arguably, we should do this check on32-bit machines too.
62 | CHECK(--ref_count_ != std::numeric_limits::max());
63 | }
64 | #endif
65 |
66 | #if !defined(ARCH_CPU_X86_FAMILY)
67 | bool RefCountedThreadSafeBase::Release() const { return ReleaseImpl(); }
68 | void RefCountedThreadSafeBase::AddRef() const { AddRefImpl(); }
69 | void RefCountedThreadSafeBase::AddRefWithCheck() const {
70 | AddRefWithCheckImpl();
71 | }
72 | #endif
73 |
74 | #if DCHECK_IS_ON()
75 | bool RefCountedBase::CalledOnValidThread() const {
76 | return thread_checker_.CalledOnValidThread() ||
77 | g_cross_thread_ref_count_access_allow_count.load() != 0;
78 | }
79 | #endif
80 |
81 | #if DCHECK_IS_ON()
82 | ScopedAllowCrossThreadRefCountAccess::ScopedAllowCrossThreadRefCountAccess() {
83 | ++g_cross_thread_ref_count_access_allow_count;
84 | }
85 |
86 | ScopedAllowCrossThreadRefCountAccess::~ScopedAllowCrossThreadRefCountAccess() {
87 | --g_cross_thread_ref_count_access_allow_count;
88 | }
89 | #endif
90 |
91 | } // namespace subtle
92 | } // namespace base
93 |
--------------------------------------------------------------------------------
/src/base/memory/weak_ptr.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | #include "base/memory/weak_ptr.h"
6 |
7 | namespace base {
8 | namespace internal {
9 |
10 | WeakReference::Flag::Flag() {
11 | // Flags only become bound when checked for validity, or invalidated,
12 | // so that we can check that later validity/invalidation operations on
13 | // the same Flag take place on the same threadd thread.
14 | thread_checker_.DetachFromThread();
15 | }
16 |
17 | void WeakReference::Flag::Invalidate() {
18 | // The flag being invalidated with a single ref implies that there are no
19 | // weak pointers in existence. Allow deletion on other thread in this case.
20 | #if DCHECK_IS_ON()
21 | DCHECK(thread_checker_.CalledOnValidThread() || HasOneRef())
22 | << "WeakPtrs must be invalidated on the same thread as where "
23 | << "they are bound.\n";
24 | #endif
25 | invalidated_.Set();
26 | }
27 |
28 | bool WeakReference::Flag::IsValid() const {
29 | // WeakPtrs must be checked on the same threadd thread.
30 | DCHECK(thread_checker_.CalledOnValidThread());
31 | return !invalidated_.IsSet();
32 | }
33 |
34 | bool WeakReference::Flag::MaybeValid() const { return !invalidated_.IsSet(); }
35 |
36 | void WeakReference::Flag::DetachFromThread() {
37 | thread_checker_.DetachFromThread();
38 | }
39 |
40 | WeakReference::Flag::~Flag() = default;
41 |
42 | WeakReference::WeakReference() = default;
43 |
44 | WeakReference::WeakReference(const scoped_refptr& flag) : flag_(flag) {}
45 |
46 | WeakReference::~WeakReference() = default;
47 |
48 | WeakReference::WeakReference(WeakReference&& other) noexcept = default;
49 |
50 | WeakReference::WeakReference(const WeakReference& other) = default;
51 |
52 | bool WeakReference::IsValid() const { return flag_ && flag_->IsValid(); }
53 |
54 | bool WeakReference::MaybeValid() const { return flag_ && flag_->MaybeValid(); }
55 |
56 | WeakReferenceOwner::WeakReferenceOwner()
57 | : flag_(MakeRefCounted()) {}
58 |
59 | WeakReferenceOwner::~WeakReferenceOwner() { flag_->Invalidate(); }
60 |
61 | WeakReference WeakReferenceOwner::GetRef() const {
62 | // If we hold the last reference to the Flag then detach the ThreadChecker.
63 | if (!HasRefs()) {
64 | flag_->DetachFromThread();
65 | }
66 |
67 | return WeakReference(flag_);
68 | }
69 |
70 | void WeakReferenceOwner::Invalidate() {
71 | flag_->Invalidate();
72 | flag_ = MakeRefCounted();
73 | }
74 |
75 | WeakPtrBase::WeakPtrBase() : ptr_(0) {}
76 |
77 | WeakPtrBase::~WeakPtrBase() = default;
78 |
79 | WeakPtrBase::WeakPtrBase(const WeakReference& ref, uintptr_t ptr)
80 | : ref_(ref), ptr_(ptr) {
81 | DCHECK(ptr_);
82 | }
83 |
84 | WeakPtrFactoryBase::WeakPtrFactoryBase(uintptr_t ptr) : ptr_(ptr) {
85 | DCHECK(ptr_);
86 | }
87 |
88 | WeakPtrFactoryBase::~WeakPtrFactoryBase() { ptr_ = 0; }
89 |
90 | } // namespace internal
91 | } // namespace base
92 |
--------------------------------------------------------------------------------
/src/base/third_party/concurrentqueue/lightweightsemaphore.h:
--------------------------------------------------------------------------------
1 | // Provides an efficient implementation of a semaphore (LightweightSemaphore).
2 | // This is an extension of Jeff Preshing's sempahore implementation (licensed
3 | // under the terms of its separate zlib license) that has been adapted and
4 | // extended by Cameron Desrochers.
5 |
6 | #pragma once
7 |
8 | #include // For std::size_t
9 | #include
10 | #include // For std::make_signed
11 |
12 | #if defined(_WIN32)
13 | // Avoid including windows.h in a header; we only need a handful of
14 | // items, so we'll redeclare them here (this is relatively safe since
15 | // the API generally has to remain stable between Windows versions).
16 | // I know this is an ugly hack but it still beats polluting the global
17 | // namespace with thousands of generic names or adding a .cpp for nothing.
18 | extern "C" {
19 | struct _SECURITY_ATTRIBUTES;
20 | __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName);
21 | __declspec(dllimport) int __stdcall CloseHandle(void* hObject);
22 | __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds);
23 | __declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount);
24 | }
25 | #elif defined(__MACH__)
26 | #include
27 | #elif defined(__MVS__)
28 | #include
29 | #elif defined(__unix__)
30 | #include
31 |
32 | #if defined(__GLIBC_PREREQ) && defined(_GNU_SOURCE)
33 | #if __GLIBC_PREREQ(2,30)
34 | #define MOODYCAMEL_LIGHTWEIGHTSEMAPHORE_MONOTONIC
35 | #endif
36 | #endif
37 | #endif
38 |
39 | namespace moodycamel
40 | {
41 | namespace details
42 | {
43 |
44 | // Code in the mpmc_sema namespace below is an adaptation of Jeff Preshing's
45 | // portable + lightweight semaphore implementations, originally from
46 | // https://github.com/preshing/cpp11-on-multicore/blob/master/common/sema.h
47 | // LICENSE:
48 | // Copyright (c) 2015 Jeff Preshing
49 | //
50 | // This software is provided 'as-is', without any express or implied
51 | // warranty. In no event will the authors be held liable for any damages
52 | // arising from the use of this software.
53 | //
54 | // Permission is granted to anyone to use this software for any purpose,
55 | // including commercial applications, and to alter it and redistribute it
56 | // freely, subject to the following restrictions:
57 | //
58 | // 1. The origin of this software must not be misrepresented; you must not
59 | // claim that you wrote the original software. If you use this software
60 | // in a product, an acknowledgement in the product documentation would be
61 | // appreciated but is not required.
62 | // 2. Altered source versions must be plainly marked as such, and must not be
63 | // misrepresented as being the original software.
64 | // 3. This notice may not be removed or altered from any source distribution.
65 | #if defined(_WIN32)
66 | class Semaphore
67 | {
68 | private:
69 | void* m_hSema;
70 |
71 | Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
72 | Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
73 |
74 | public:
75 | Semaphore(int initialCount = 0)
76 | {
77 | assert(initialCount >= 0);
78 | const long maxLong = 0x7fffffff;
79 | m_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr);
80 | assert(m_hSema);
81 | }
82 |
83 | ~Semaphore()
84 | {
85 | CloseHandle(m_hSema);
86 | }
87 |
88 | bool wait()
89 | {
90 | const unsigned long infinite = 0xffffffff;
91 | return WaitForSingleObject(m_hSema, infinite) == 0;
92 | }
93 |
94 | bool try_wait()
95 | {
96 | return WaitForSingleObject(m_hSema, 0) == 0;
97 | }
98 |
99 | bool timed_wait(std::uint64_t usecs)
100 | {
101 | return WaitForSingleObject(m_hSema, (unsigned long)(usecs / 1000)) == 0;
102 | }
103 |
104 | void signal(int count = 1)
105 | {
106 | while (!ReleaseSemaphore(m_hSema, count, nullptr));
107 | }
108 | };
109 | #elif defined(__MACH__)
110 | //---------------------------------------------------------
111 | // Semaphore (Apple iOS and OSX)
112 | // Can't use POSIX semaphores due to http://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html
113 | //---------------------------------------------------------
114 | class Semaphore
115 | {
116 | private:
117 | semaphore_t m_sema;
118 |
119 | Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
120 | Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
121 |
122 | public:
123 | Semaphore(int initialCount = 0)
124 | {
125 | assert(initialCount >= 0);
126 | kern_return_t rc = semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
127 | assert(rc == KERN_SUCCESS);
128 | (void)rc;
129 | }
130 |
131 | ~Semaphore()
132 | {
133 | semaphore_destroy(mach_task_self(), m_sema);
134 | }
135 |
136 | bool wait()
137 | {
138 | return semaphore_wait(m_sema) == KERN_SUCCESS;
139 | }
140 |
141 | bool try_wait()
142 | {
143 | return timed_wait(0);
144 | }
145 |
146 | bool timed_wait(std::uint64_t timeout_usecs)
147 | {
148 | mach_timespec_t ts;
149 | ts.tv_sec = static_cast(timeout_usecs / 1000000);
150 | ts.tv_nsec = static_cast((timeout_usecs % 1000000) * 1000);
151 |
152 | // added in OSX 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/modules/Darwin.html
153 | kern_return_t rc = semaphore_timedwait(m_sema, ts);
154 | return rc == KERN_SUCCESS;
155 | }
156 |
157 | void signal()
158 | {
159 | while (semaphore_signal(m_sema) != KERN_SUCCESS);
160 | }
161 |
162 | void signal(int count)
163 | {
164 | while (count-- > 0)
165 | {
166 | while (semaphore_signal(m_sema) != KERN_SUCCESS);
167 | }
168 | }
169 | };
170 | #elif defined(__unix__) || defined(__MVS__)
171 | //---------------------------------------------------------
172 | // Semaphore (POSIX, Linux, zOS)
173 | //---------------------------------------------------------
174 | class Semaphore
175 | {
176 | private:
177 | sem_t m_sema;
178 |
179 | Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
180 | Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
181 |
182 | public:
183 | Semaphore(int initialCount = 0)
184 | {
185 | assert(initialCount >= 0);
186 | int rc = sem_init(&m_sema, 0, static_cast(initialCount));
187 | assert(rc == 0);
188 | (void)rc;
189 | }
190 |
191 | ~Semaphore()
192 | {
193 | sem_destroy(&m_sema);
194 | }
195 |
196 | bool wait()
197 | {
198 | // http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error
199 | int rc;
200 | do {
201 | rc = sem_wait(&m_sema);
202 | } while (rc == -1 && errno == EINTR);
203 | return rc == 0;
204 | }
205 |
206 | bool try_wait()
207 | {
208 | int rc;
209 | do {
210 | rc = sem_trywait(&m_sema);
211 | } while (rc == -1 && errno == EINTR);
212 | return rc == 0;
213 | }
214 |
215 | bool timed_wait(std::uint64_t usecs)
216 | {
217 | struct timespec ts;
218 | const int usecs_in_1_sec = 1000000;
219 | const int nsecs_in_1_sec = 1000000000;
220 | #ifdef MOODYCAMEL_LIGHTWEIGHTSEMAPHORE_MONOTONIC
221 | clock_gettime(CLOCK_MONOTONIC, &ts);
222 | #else
223 | clock_gettime(CLOCK_REALTIME, &ts);
224 | #endif
225 | ts.tv_sec += (time_t)(usecs / usecs_in_1_sec);
226 | ts.tv_nsec += (long)(usecs % usecs_in_1_sec) * 1000;
227 | // sem_timedwait bombs if you have more than 1e9 in tv_nsec
228 | // so we have to clean things up before passing it in
229 | if (ts.tv_nsec >= nsecs_in_1_sec) {
230 | ts.tv_nsec -= nsecs_in_1_sec;
231 | ++ts.tv_sec;
232 | }
233 |
234 | int rc;
235 | do {
236 | #ifdef MOODYCAMEL_LIGHTWEIGHTSEMAPHORE_MONOTONIC
237 | rc = sem_clockwait(&m_sema, CLOCK_MONOTONIC, &ts);
238 | #else
239 | rc = sem_timedwait(&m_sema, &ts);
240 | #endif
241 | } while (rc == -1 && errno == EINTR);
242 | return rc == 0;
243 | }
244 |
245 | void signal()
246 | {
247 | while (sem_post(&m_sema) == -1);
248 | }
249 |
250 | void signal(int count)
251 | {
252 | while (count-- > 0)
253 | {
254 | while (sem_post(&m_sema) == -1);
255 | }
256 | }
257 | };
258 | #else
259 | #error Unsupported platform! (No semaphore wrapper available)
260 | #endif
261 |
262 | } // end namespace details
263 |
264 |
265 | //---------------------------------------------------------
266 | // LightweightSemaphore
267 | //---------------------------------------------------------
268 | class LightweightSemaphore
269 | {
270 | public:
271 | typedef std::make_signed::type ssize_t;
272 |
273 | private:
274 | std::atomic m_count;
275 | details::Semaphore m_sema;
276 | int m_maxSpins;
277 |
278 | bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1)
279 | {
280 | ssize_t oldCount;
281 | int spin = m_maxSpins;
282 | while (--spin >= 0)
283 | {
284 | oldCount = m_count.load(std::memory_order_relaxed);
285 | if ((oldCount > 0) && m_count.compare_exchange_strong(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))
286 | return true;
287 | std::atomic_signal_fence(std::memory_order_acquire); // Prevent the compiler from collapsing the loop.
288 | }
289 | oldCount = m_count.fetch_sub(1, std::memory_order_acquire);
290 | if (oldCount > 0)
291 | return true;
292 | if (timeout_usecs < 0)
293 | {
294 | if (m_sema.wait())
295 | return true;
296 | }
297 | if (timeout_usecs > 0 && m_sema.timed_wait((std::uint64_t)timeout_usecs))
298 | return true;
299 | // At this point, we've timed out waiting for the semaphore, but the
300 | // count is still decremented indicating we may still be waiting on
301 | // it. So we have to re-adjust the count, but only if the semaphore
302 | // wasn't signaled enough times for us too since then. If it was, we
303 | // need to release the semaphore too.
304 | while (true)
305 | {
306 | oldCount = m_count.load(std::memory_order_acquire);
307 | if (oldCount >= 0 && m_sema.try_wait())
308 | return true;
309 | if (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))
310 | return false;
311 | }
312 | }
313 |
314 | ssize_t waitManyWithPartialSpinning(ssize_t max, std::int64_t timeout_usecs = -1)
315 | {
316 | assert(max > 0);
317 | ssize_t oldCount;
318 | int spin = m_maxSpins;
319 | while (--spin >= 0)
320 | {
321 | oldCount = m_count.load(std::memory_order_relaxed);
322 | if (oldCount > 0)
323 | {
324 | ssize_t newCount = oldCount > max ? oldCount - max : 0;
325 | if (m_count.compare_exchange_strong(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))
326 | return oldCount - newCount;
327 | }
328 | std::atomic_signal_fence(std::memory_order_acquire);
329 | }
330 | oldCount = m_count.fetch_sub(1, std::memory_order_acquire);
331 | if (oldCount <= 0)
332 | {
333 | if ((timeout_usecs == 0) || (timeout_usecs < 0 && !m_sema.wait()) || (timeout_usecs > 0 && !m_sema.timed_wait((std::uint64_t)timeout_usecs)))
334 | {
335 | while (true)
336 | {
337 | oldCount = m_count.load(std::memory_order_acquire);
338 | if (oldCount >= 0 && m_sema.try_wait())
339 | break;
340 | if (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))
341 | return 0;
342 | }
343 | }
344 | }
345 | if (max > 1)
346 | return 1 + tryWaitMany(max - 1);
347 | return 1;
348 | }
349 |
350 | public:
351 | LightweightSemaphore(ssize_t initialCount = 0, int maxSpins = 10000) : m_count(initialCount), m_maxSpins(maxSpins)
352 | {
353 | assert(initialCount >= 0);
354 | assert(maxSpins >= 0);
355 | }
356 |
357 | bool tryWait()
358 | {
359 | ssize_t oldCount = m_count.load(std::memory_order_relaxed);
360 | while (oldCount > 0)
361 | {
362 | if (m_count.compare_exchange_weak(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))
363 | return true;
364 | }
365 | return false;
366 | }
367 |
368 | bool wait()
369 | {
370 | return tryWait() || waitWithPartialSpinning();
371 | }
372 |
373 | bool wait(std::int64_t timeout_usecs)
374 | {
375 | return tryWait() || waitWithPartialSpinning(timeout_usecs);
376 | }
377 |
378 | // Acquires between 0 and (greedily) max, inclusive
379 | ssize_t tryWaitMany(ssize_t max)
380 | {
381 | assert(max >= 0);
382 | ssize_t oldCount = m_count.load(std::memory_order_relaxed);
383 | while (oldCount > 0)
384 | {
385 | ssize_t newCount = oldCount > max ? oldCount - max : 0;
386 | if (m_count.compare_exchange_weak(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))
387 | return oldCount - newCount;
388 | }
389 | return 0;
390 | }
391 |
392 | // Acquires at least one, and (greedily) at most max
393 | ssize_t waitMany(ssize_t max, std::int64_t timeout_usecs)
394 | {
395 | assert(max >= 0);
396 | ssize_t result = tryWaitMany(max);
397 | if (result == 0 && max > 0)
398 | result = waitManyWithPartialSpinning(max, timeout_usecs);
399 | return result;
400 | }
401 |
402 | ssize_t waitMany(ssize_t max)
403 | {
404 | ssize_t result = waitMany(max, -1);
405 | assert(result > 0);
406 | return result;
407 | }
408 |
409 | void signal(ssize_t count = 1)
410 | {
411 | assert(count >= 0);
412 | ssize_t oldCount = m_count.fetch_add(count, std::memory_order_release);
413 | ssize_t toRelease = -oldCount < count ? -oldCount : count;
414 | if (toRelease > 0)
415 | {
416 | m_sema.signal((int)toRelease);
417 | }
418 | }
419 |
420 | std::size_t availableApprox() const
421 | {
422 | ssize_t count = m_count.load(std::memory_order_relaxed);
423 | return count > 0 ? static_cast(count) : 0;
424 | }
425 | };
426 |
427 | } // end namespace moodycamel
428 |
--------------------------------------------------------------------------------
/src/base/thread/thread_checker.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
2 | // Google Inc. All rights reserved.
3 | //
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are
6 | // met:
7 | //
8 | // * Redistributions of source code must retain the above copyright
9 | // notice, this list of conditions and the following disclaimer.
10 | // * Redistributions in binary form must reproduce the above
11 | // copyright notice, this list of conditions and the following disclaimer
12 | // in the documentation and/or other materials provided with the
13 | // distribution.
14 | // * Neither the name of Google Inc. nor the name Chromium Embedded
15 | // Framework nor the names of its contributors may be used to endorse
16 | // or promote products derived from this software without specific prior
17 | // written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | #ifndef BASE_THREAD_THREAD_CHECKER_H_
32 | #define BASE_THREAD_THREAD_CHECKER_H_
33 |
34 | // The following is substantially similar to the Chromium implementation.
35 | // If the Chromium implementation diverges the below implementation should be
36 | // updated to match.
37 |
38 | #include "base/debug/logging.h"
39 |
40 | namespace base {
41 |
42 | namespace internal {
43 |
44 | ///
45 | /// Do nothing implementation, for use in release mode.
46 | ///
47 | /// Note: You should almost always use the ThreadChecker class to get the
48 | /// right version for your build configuration.
49 | ///
50 | class ThreadCheckerDoNothing {
51 | public:
52 | bool CalledOnValidThread() const { return true; }
53 |
54 | void DetachFromThread() {}
55 | };
56 |
57 | } // namespace internal
58 |
59 | class ThreadChecker : public internal::ThreadCheckerDoNothing {};
60 |
61 | } // namespace base
62 |
63 | #endif // BASE_THREAD_THREAD_CHECKER_H_
64 |
--------------------------------------------------------------------------------
/src/edgeview_data.cc:
--------------------------------------------------------------------------------
1 | #include "edgeview_data.h"
2 |
3 | #include "ev_network.h"
4 |
5 | namespace edgeview {
6 |
7 | ResourceRequestCallback::~ResourceRequestCallback() { ContinueRequest(this, nullptr); }
8 |
9 | } // namespace edgeview
10 |
--------------------------------------------------------------------------------
/src/edgeview_data.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include "base/memory/ref_counted.h"
7 | #include "base/memory/weak_ptr.h"
8 | #include "ev_msgpump.h"
9 | #include "event_notify.h"
10 | #include "util.h"
11 | #include "webview_host.h"
12 |
13 | namespace edgeview {
14 |
15 | class EdgeWidgetHost;
16 | class BrowserEventDispatcher;
17 | struct FrameData;
18 |
19 | struct StrMapElement {
20 | LPCSTR key;
21 | LPCSTR value;
22 | };
23 |
24 | class Semaphore : public base::RefCounted {
25 | public:
26 | Semaphore() : atomic(false) {}
27 | ~Semaphore() = default;
28 |
29 | Semaphore(const Semaphore&) = delete;
30 | Semaphore& operator=(const Semaphore&) = delete;
31 |
32 | void Notify() { atomic.store(true); }
33 | bool IsTriggered() { return atomic.load(); }
34 | void Reset() { atomic.store(false); }
35 |
36 | private:
37 | std::atomic_bool atomic;
38 | };
39 |
40 | struct EnvironmentData : public base::RefCounted {
41 | WRL::ComPtr core_env;
42 | scoped_refptr msg_pump;
43 | scoped_refptr semaphore_flag;
44 |
45 | std::thread::id ui_thread;
46 |
47 | base::WeakPtrFactory weak_ptr_{this};
48 |
49 | EnvironmentData() = default;
50 |
51 | void PostEvent(base::OnceClosure event_notify) {
52 | // Always async running on ui thread
53 | msg_pump->PostTask(std::move(event_notify));
54 | }
55 |
56 | void PostUITask(base::OnceClosure task) {
57 | if (RunningOnUIThread()) {
58 | return std::move(task).Run();
59 | }
60 |
61 | // Only non UI thread should be post
62 | msg_pump->PostTask(std::move(task));
63 | }
64 |
65 | bool RunningOnUIThread() { return std::this_thread::get_id() == ui_thread; }
66 |
67 | scoped_refptr semaphore() const {
68 | semaphore_flag->Reset();
69 | return semaphore_flag;
70 | }
71 |
72 | bool SyncWaitIfNeed() {
73 | if (semaphore_flag->IsTriggered()) return false;
74 |
75 | if (!RunningOnUIThread()) {
76 | // Only non UI thread should be sync
77 | while (!semaphore_flag->IsTriggered()) {
78 | // Yield current thread
79 | std::this_thread::sleep_for(std::chrono::milliseconds(1));
80 | }
81 | } else {
82 | MSG pump_messsage{0};
83 | while (!semaphore_flag->IsTriggered()) {
84 | if (PeekMessage(&pump_messsage, nullptr, 0, 0, PM_REMOVE)) {
85 | TranslateMessage(&pump_messsage);
86 | DispatchMessage(&pump_messsage);
87 |
88 | if (pump_messsage.message == WM_QUIT) break;
89 | }
90 | }
91 | }
92 |
93 | // Reset
94 | semaphore_flag->Reset();
95 |
96 | return true;
97 | }
98 | };
99 |
100 | struct BrowserData : public base::RefCounted {
101 | base::WeakPtr parent;
102 |
103 | WRL::ComPtr core_controller;
104 | WRL::ComPtr core_webview;
105 | // Maybe nullptr
106 | WRL::ComPtr core_composition = nullptr;
107 | // Maybe nullptr
108 | scoped_refptr browser_window = nullptr;
109 | scoped_refptr dispatcher;
110 | LPVOID pCallback = nullptr;
111 |
112 | std::vector> frames;
113 |
114 | base::WeakPtrFactory weak_ptr_{this};
115 |
116 | BrowserData() = default;
117 | };
118 |
119 | struct FrameData : public base::RefCounted {
120 | base::WeakPtr browser;
121 |
122 | WRL::ComPtr core_frame;
123 | std::string url;
124 |
125 | base::WeakPtrFactory weak_ptr_{this};
126 |
127 | FrameData(WRL::ComPtr frame) : core_frame(frame) {}
128 | };
129 |
130 | struct NewWindowDelegate : public base::RefCounted {
131 | base::WeakPtr browser;
132 |
133 | WRL::ComPtr core_newwindow;
134 | WRL::ComPtr internal_deferral;
135 |
136 | NewWindowDelegate() = default;
137 | };
138 |
139 | struct ScriptDialogDelegate : public base::RefCounted {
140 | base::WeakPtr browser;
141 |
142 | WRL::ComPtr core_dialog;
143 | WRL::ComPtr internal_deferral;
144 |
145 | ScriptDialogDelegate() = default;
146 | };
147 |
148 | struct ContextMenuParams : public base::RefCounted {
149 | base::WeakPtr browser;
150 |
151 | WRL::ComPtr core_menu;
152 | WRL::ComPtr internal_deferral;
153 |
154 | ContextMenuParams() = default;
155 | };
156 |
157 | struct ContextMenuCollection : public base::RefCounted {
158 | base::WeakPtr browser;
159 |
160 | WRL::ComPtr core_list;
161 |
162 | ContextMenuCollection() = default;
163 | };
164 |
165 | struct ContextMenuItem : public base::RefCounted {
166 | base::WeakPtr browser;
167 |
168 | WRL::ComPtr core_item;
169 |
170 | ContextMenuItem() = default;
171 | };
172 |
173 | struct PermissionDelegate : public base::RefCounted {
174 | base::WeakPtr browser;
175 |
176 | WRL::ComPtr core_delegate;
177 | WRL::ComPtr internal_deferral;
178 |
179 | PermissionDelegate() = default;
180 | };
181 |
182 | struct CookieManagerData : public base::RefCounted {
183 | base::WeakPtr browser;
184 |
185 | WRL::ComPtr core_manager;
186 |
187 | CookieManagerData() = default;
188 | };
189 |
190 | struct ResourceRequestCallback
191 | : public base::RefCounted {
192 | base::WeakPtr browser;
193 |
194 | json event_parameter;
195 |
196 | ResourceRequestCallback() = default;
197 | };
198 |
199 | struct ResourceResponseCallback
200 | : public base::RefCounted {
201 | base::WeakPtr browser;
202 |
203 | json event_parameter;
204 |
205 | ResourceResponseCallback() = default;
206 | };
207 |
208 | struct BasicAuthenticationCallback
209 | : public base::RefCounted {
210 | base::WeakPtr browser;
211 |
212 | WRL::ComPtr core_callback;
213 | WRL::ComPtr internal_deferral;
214 |
215 | BasicAuthenticationCallback() = default;
216 | };
217 |
218 | struct DownloadOperation : public base::RefCounted {
219 | base::WeakPtr browser;
220 |
221 | WRL::ComPtr core_operation;
222 |
223 | DownloadOperation() = default;
224 | };
225 |
226 | struct DownloadConfirm : public base::RefCounted {
227 | base::WeakPtr