tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mozmemory_stall.h (2497B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozjemalloc_stall_h
      8 #define mozjemalloc_stall_h
      9 
     10 #include <optional>
     11 
     12 #if defined(MOZ_MEMORY) && defined(XP_WIN)
     13 #  include "mozmemory_wrap.h"
     14 #endif
     15 
     16 // See
     17 // https://hacks.mozilla.org/2022/11/improving-firefox-stability-with-this-one-weird-trick/
     18 
     19 namespace mozilla {
     20 
     21 namespace detail {
     22 // Helper for StallAndRetry error messages.
     23 template <typename T>
     24 constexpr bool is_std_optional = false;
     25 template <typename T>
     26 constexpr bool is_std_optional<std::optional<T>> = true;
     27 }  // namespace detail
     28 
     29 struct StallSpecs {
     30  // Maximum number of retry-attempts before giving up.
     31  size_t maxAttempts;
     32  // Delay time between successive events.
     33  size_t delayMs;
     34 
     35  // Retry a fallible operation until it succeeds or until we've run out of
     36  // retries.
     37  //
     38  // Note that this invokes `aDelayFunc` immediately upon being called! It's
     39  // intended for use in the unhappy path, after an initial attempt has failed.
     40  //
     41  // The function type here may be read:
     42  // ```
     43  // fn StallAndRetry<R>(
     44  //     delay_func: impl Fn(usize) -> (),
     45  //     operation: impl Fn() -> Option<R>,
     46  // ) -> Option<R>;
     47  // ```
     48  //
     49  template <typename DelayFunc, typename OpFunc>
     50  auto StallAndRetry(DelayFunc&& aDelayFunc, OpFunc&& aOperation) const
     51      -> decltype(aOperation()) {
     52    {
     53      // Explicit typecheck for OpFunc, to provide an explicit error message.
     54      using detail::is_std_optional;
     55      static_assert(is_std_optional<decltype(aOperation())>,
     56                    "aOperation() must return std::optional");
     57 
     58      // (clang's existing error messages suffice for aDelayFunc.)
     59    }
     60 
     61    for (size_t i = 0; i < maxAttempts; ++i) {
     62      aDelayFunc(delayMs);
     63      if (const auto opt = aOperation()) {
     64        return opt;
     65      }
     66    }
     67    return std::nullopt;
     68  }
     69 };
     70 
     71 #if defined(MOZ_MEMORY) && defined(XP_WIN)
     72 MOZ_JEMALLOC_API StallSpecs GetAllocatorStallSpecs();
     73 MOZ_JEMALLOC_API_NODISCARD void* MozVirtualAlloc(void* lpAddress, size_t dwSize,
     74                                                 uint32_t flAllocationType,
     75                                                 uint32_t flProtect);
     76 #endif
     77 
     78 }  // namespace mozilla
     79 
     80 #endif  // mozjemalloc_stall_h