sapling/eden/fs/utils/IDGen.cpp
Adam Simpkins aa5e6c7295 update license headers in C++ files
Summary:
Update the copyright & license headers in C++ files to reflect the
relicensing to GPLv2

Reviewed By: wez

Differential Revision: D15487078

fbshipit-source-id: 19f24c933a64ecad0d3a692d0f8d2a38b4194b1d
2019-06-19 17:02:45 -07:00

56 lines
1.5 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
#include "eden/fs/utils/IDGen.h"
#include <folly/Likely.h>
#include <folly/lang/Align.h>
#include <atomic>
namespace {
/**
* Allocating one unique ID per nanosecond would wrap around in over 500 years.
*
* Allocated to its own cache line.
*/
struct alignas(folly::hardware_destructive_interference_size) {
std::atomic<uint64_t> counter{0};
} global;
thread_local uint64_t localCounter{0};
/**
* Number of unique IDs to hand out to a thread at a time. This avoids cache
* line contention on globalCounter. kRangeSize should be large enough to reduce
* contention but small enough that the pathological case of threads being
* spawned in a tight loop, each allocating one unique ID, does not rapidly
* exhaust the 64-bit counter space.
*
* I haven't measured, but I'd be surprised if a thread could be created in
* 2000 nanoseconds.
*/
constexpr uint64_t kRangeSize = 2048;
static_assert(
(kRangeSize & (kRangeSize - 1)) == 0,
"kRangeSize must be a power of two");
} // namespace
namespace facebook {
namespace eden {
uint64_t generateUniqueID() noexcept {
uint64_t current = localCounter;
if (UNLIKELY(current % kRangeSize == 0)) {
current = global.counter.fetch_add(kRangeSize, std::memory_order_relaxed);
}
++current;
localCounter = current;
return current;
}
} // namespace eden
} // namespace facebook