Commit a821d1c9 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Use a fixed mempool capacity in LifoSem

Summary: [Folly] Use a fixed mempool capacity in `LifoSem`, simplifying usage.

Reviewed By: nbronson

Differential Revision: D17251982

fbshipit-source-id: e3bce99204daef178418268f1d195365400df885
parent f65c05bb
/*
* Copyright 2014-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/synchronization/LifoSem.h>
/// Raw node storage is preallocated in a contiguous memory segment,
/// but we use an anonymous mmap so the physical memory used (RSS) will
/// only reflect the maximum number of waiters that actually existed
/// concurrently. For blocked threads the max node count is limited by the
/// number of threads, so we can conservatively estimate that this will be
/// < 10k. For LifoEventSem, however, we could potentially have many more.
///
/// On a 64-bit architecture each LifoSemRawNode takes 16 bytes. We make
/// the pool 1 million entries.
LIFOSEM_DECLARE_POOL(std::atomic, 1000000)
namespace folly {
ShutdownSemError::ShutdownSemError(const std::string& msg)
: std::runtime_error(msg) {}
ShutdownSemError::~ShutdownSemError() noexcept {}
} // namespace folly
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <folly/Likely.h> #include <folly/Likely.h>
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/Traits.h> #include <folly/Traits.h>
#include <folly/detail/StaticSingletonManager.h>
#include <folly/lang/SafeAssert.h> #include <folly/lang/SafeAssert.h>
#include <folly/synchronization/AtomicStruct.h> #include <folly/synchronization/AtomicStruct.h>
#include <folly/synchronization/SaturatingSemaphore.h> #include <folly/synchronization/SaturatingSemaphore.h>
...@@ -96,9 +97,9 @@ struct LifoSemImpl; ...@@ -96,9 +97,9 @@ struct LifoSemImpl;
typedef LifoSemImpl<> LifoSem; typedef LifoSemImpl<> LifoSem;
/// The exception thrown when wait()ing on an isShutdown() LifoSem /// The exception thrown when wait()ing on an isShutdown() LifoSem
struct FOLLY_EXPORT ShutdownSemError : public std::runtime_error { class FOLLY_EXPORT ShutdownSemError : public std::runtime_error {
explicit ShutdownSemError(const std::string& msg); public:
~ShutdownSemError() noexcept override; using std::runtime_error::runtime_error;
}; };
namespace detail { namespace detail {
...@@ -149,22 +150,27 @@ struct LifoSemRawNode { ...@@ -149,22 +150,27 @@ struct LifoSemRawNode {
Pool; Pool;
/// Storage for all of the waiter nodes for LifoSem-s that use Atom /// Storage for all of the waiter nodes for LifoSem-s that use Atom
static Pool& pool(); static Pool& pool() {
}; return detail::createGlobal<PoolImpl, void>();
/// Use this macro to declare the static storage that backs the raw nodes
/// for the specified atomic type
#define LIFOSEM_DECLARE_POOL(Atom, capacity) \
namespace folly { \
namespace detail { \
template <> \
LifoSemRawNode<Atom>::Pool& LifoSemRawNode<Atom>::pool() { \
static Pool* instance = new Pool((capacity)); \
return *instance; \
} \
} \
} }
private:
struct PoolImpl : Pool {
/// Raw node storage is preallocated in a contiguous memory segment,
/// but we use an anonymous mmap so the physical memory used (RSS) will
/// only reflect the maximum number of waiters that actually existed
/// concurrently. For blocked threads the max node count is limited by the
/// number of threads, so we can conservatively estimate that this will be
/// < 10k. For LifoEventSem, however, we could potentially have many more.
///
/// On a 64-bit architecture each LifoSemRawNode takes 16 bytes. We make
/// the pool 1 million entries.
static constexpr size_t capacity = 1 << 20;
PoolImpl() : Pool(static_cast<uint32_t>(capacity)) {}
};
};
/// Handoff is a type not bigger than a void* that knows how to perform a /// Handoff is a type not bigger than a void* that knows how to perform a
/// single post() -> wait() communication. It must have a post() method. /// single post() -> wait() communication. It must have a post() method.
/// If it has a wait() method then LifoSemBase's wait() implementation /// If it has a wait() method then LifoSemBase's wait() implementation
......
...@@ -32,8 +32,6 @@ using namespace folly::test; ...@@ -32,8 +32,6 @@ using namespace folly::test;
typedef LifoSemImpl<DeterministicAtomic> DLifoSem; typedef LifoSemImpl<DeterministicAtomic> DLifoSem;
typedef DeterministicSchedule DSched; typedef DeterministicSchedule DSched;
LIFOSEM_DECLARE_POOL(DeterministicAtomic, 100000)
class LifoSemTest : public testing::Test { class LifoSemTest : public testing::Test {
private: private:
// pre-init the pool to avoid deadlock when using DeterministicAtomic // pre-init the pool to avoid deadlock when using DeterministicAtomic
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment