/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef FOLLY_LIFOSEM_H
-#define FOLLY_LIFOSEM_H
+#pragma once
#include <string.h>
#include <stdint.h>
#include <memory>
#include <system_error>
-#include "folly/AtomicStruct.h"
-#include "folly/Baton.h"
-#include "folly/IndexedMemPool.h"
-#include "folly/Likely.h"
-#include "folly/detail/CacheLocality.h"
+#include <folly/AtomicStruct.h>
+#include <folly/Baton.h>
+#include <folly/IndexedMemPool.h>
+#include <folly/Likely.h>
+#include <folly/detail/CacheLocality.h>
namespace folly {
typedef folly::IndexedMemPool<LifoSemRawNode<Atom>,32,200,Atom> Pool;
/// Storage for all of the waiter nodes for LifoSem-s that use Atom
- static Pool pool;
+ static Pool& pool();
};
/// Use this macro to declare the static storage that backs the raw nodes
/// for the specified atomic type
-#define LIFOSEM_DECLARE_POOL(Atom, capacity) \
- template<> \
- folly::detail::LifoSemRawNode<Atom>::Pool \
- folly::detail::LifoSemRawNode<Atom>::pool((capacity));
+#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; \
+ } \
+ } \
+ }
/// 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.
struct LifoSemNodeRecycler {
void operator()(LifoSemNode<Handoff,Atom>* elem) const {
elem->destroy();
- auto idx = LifoSemRawNode<Atom>::pool.locateElem(elem);
- LifoSemRawNode<Atom>::pool.recycleIndex(idx);
+ auto idx = LifoSemRawNode<Atom>::pool().locateElem(elem);
+ LifoSemRawNode<Atom>::pool().recycleIndex(idx);
}
};
}
/// Returns the LifoSemHead that results from pushing a new waiter node
- inline LifoSemHead withPush(uint32_t idx) const {
+ inline LifoSemHead withPush(uint32_t _idx) const {
assert(isNodeIdx() || value() == 0);
assert(!isShutdown());
- assert(idx != 0);
- return LifoSemHead{ (bits & SeqMask) | IsNodeIdxMask | idx };
+ assert(_idx != 0);
+ return LifoSemHead{ (bits & SeqMask) | IsNodeIdxMask | _idx };
}
/// Returns the LifoSemHead with value increased by delta, with
/// See LifoSemNode for more information on how to make your own.
template <typename Handoff,
template<typename> class Atom = std::atomic>
-struct LifoSemBase : boost::noncopyable {
+struct LifoSemBase {
/// Constructor
- explicit LifoSemBase(uint32_t initialValue = 0)
- : head_(LifoSemHead::fresh(initialValue)) {}
+ constexpr explicit LifoSemBase(uint32_t initialValue = 0)
+ : head_(LifoSemHead::fresh(initialValue)), padding_() {}
+
+ LifoSemBase(LifoSemBase const&) = delete;
+ LifoSemBase& operator=(LifoSemBase const&) = delete;
/// Silently saturates if value is already 2^32-1
void post() {
/// Returns a node that can be passed to decrOrLink
template <typename... Args>
UniquePtr allocateNode(Args&&... args) {
- auto idx = LifoSemRawNode<Atom>::pool.allocIndex();
+ auto idx = LifoSemRawNode<Atom>::pool().allocIndex();
if (idx != 0) {
auto& node = idxToNode(idx);
node.clearShutdownNotice();
try {
node.init(std::forward<Args>(args)...);
} catch (...) {
- LifoSemRawNode<Atom>::pool.recycleIndex(idx);
+ LifoSemRawNode<Atom>::pool().recycleIndex(idx);
throw;
}
return UniquePtr(&node);
private:
- folly::AtomicStruct<LifoSemHead,Atom> head_
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING;
+ FOLLY_ALIGN_TO_AVOID_FALSE_SHARING
+ folly::AtomicStruct<LifoSemHead,Atom> head_;
char padding_[folly::detail::CacheLocality::kFalseSharingRange -
sizeof(LifoSemHead)];
static LifoSemNode<Handoff, Atom>& idxToNode(uint32_t idx) {
- auto raw = &LifoSemRawNode<Atom>::pool[idx];
+ auto raw = &LifoSemRawNode<Atom>::pool()[idx];
return *static_cast<LifoSemNode<Handoff, Atom>*>(raw);
}
static uint32_t nodeToIdx(const LifoSemNode<Handoff, Atom>& node) {
- return LifoSemRawNode<Atom>::pool.locateElem(&node);
+ return LifoSemRawNode<Atom>::pool().locateElem(&node);
}
/// Either increments by n and returns 0, or pops a node and returns it.
template <template<typename> class Atom, class BatonType>
struct LifoSemImpl : public detail::LifoSemBase<BatonType, Atom> {
- explicit LifoSemImpl(uint32_t v = 0)
+ constexpr explicit LifoSemImpl(uint32_t v = 0)
: detail::LifoSemBase<BatonType, Atom>(v) {}
};
} // namespace folly
-
-#endif