Commit 8516df37 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

portability tweaks to ShutdownSocketSet

Summary:
`NetworkSocket::data` may not always be integral; for XROS, it is `void*` instead (as a sort of no-op). Portably handle this.

Now, treat the vector and the capacity more like a vector and capacity, using `size_t` for capacity and positions. Convert explicitly where required.

Reviewed By: Orvid

Differential Revision: D31220216

fbshipit-source-id: 47db6ed72ff9124e30dacc31c6ec0427c29b3c99
parent bc1365d3
......@@ -27,20 +27,65 @@
namespace folly {
ShutdownSocketSet::ShutdownSocketSet(int maxFd)
: maxFd_(maxFd),
using handle_t = NetworkSocket::native_handle_type;
static constexpr auto handle_tag = std::is_integral<handle_t>{};
static constexpr auto invalid_pos = ~size_t(0);
template <typename Cap>
static size_t cap_(std::false_type, Cap) {
return 0;
}
template <typename Cap, typename H = handle_t>
static size_t cap_(std::true_type, Cap cap) {
cap = cap == invalid_pos ? 0 : cap;
auto max = static_cast<Cap>(std::numeric_limits<H>::max());
return cap > max ? max : cap;
}
static size_t cap(size_t capacity) {
return cap_(handle_tag, capacity);
}
template <typename Data>
static size_t pos_(std::false_type, Data) {
return invalid_pos;
}
template <typename Data>
static size_t pos_(std::true_type, Data data) {
return to_unsigned(data);
}
static size_t pos(NetworkSocket fd) {
return fd.data == NetworkSocket::invalid_handle_value
? invalid_pos
: pos_(handle_tag, fd.data);
}
template <typename Pos>
static NetworkSocket at_(std::false_type, Pos) {
return NetworkSocket();
}
template <typename Pos>
static NetworkSocket at_(std::true_type, Pos p) {
return NetworkSocket(static_cast<NetworkSocket::native_handle_type>(p));
}
static NetworkSocket at(size_t p) {
return p == invalid_pos ? NetworkSocket() : at_(handle_tag, p);
}
ShutdownSocketSet::ShutdownSocketSet(size_t capacity)
: capacity_(cap(capacity)),
data_(static_cast<std::atomic<uint8_t>*>(
folly::checkedCalloc(size_t(maxFd), sizeof(std::atomic<uint8_t>)))),
folly::checkedCalloc(capacity_, sizeof(std::atomic<uint8_t>)))),
nullFile_("/dev/null", O_RDWR) {}
void ShutdownSocketSet::add(NetworkSocket fd) {
// Silently ignore any fds >= maxFd_, very unlikely
// Silently ignore any fds >= capacity_, very unlikely
DCHECK_NE(fd, NetworkSocket());
if (fd.data >= maxFd_) {
auto p = pos(fd);
if (p >= capacity_) {
return;
}
auto& sref = data_[size_t(fd.data)];
auto& sref = data_[p];
uint8_t prevState = FREE;
CHECK(sref.compare_exchange_strong(
prevState, IN_USE, std::memory_order_relaxed))
......@@ -49,11 +94,12 @@ void ShutdownSocketSet::add(NetworkSocket fd) {
void ShutdownSocketSet::remove(NetworkSocket fd) {
DCHECK_NE(fd, NetworkSocket());
if (fd.data >= maxFd_) {
auto p = pos(fd);
if (p >= capacity_) {
return;
}
auto& sref = data_[size_t(fd.data)];
auto& sref = data_[p];
uint8_t prevState = 0;
prevState = sref.load(std::memory_order_relaxed);
......@@ -73,11 +119,12 @@ void ShutdownSocketSet::remove(NetworkSocket fd) {
int ShutdownSocketSet::close(NetworkSocket fd) {
DCHECK_NE(fd, NetworkSocket());
if (fd.data >= maxFd_) {
auto p = pos(fd);
if (p >= capacity_) {
return folly::closeNoInt(fd);
}
auto& sref = data_[size_t(fd.data)];
auto& sref = data_[p];
uint8_t prevState = sref.load(std::memory_order_relaxed);
uint8_t newState = 0;
......@@ -102,12 +149,13 @@ int ShutdownSocketSet::close(NetworkSocket fd) {
void ShutdownSocketSet::shutdown(NetworkSocket fd, bool abortive) {
DCHECK_NE(fd, NetworkSocket());
if (fd.data >= maxFd_) {
auto p = pos(fd);
if (p >= capacity_) {
doShutdown(fd, abortive);
return;
}
auto& sref = data_[size_t(fd.data)];
auto& sref = data_[p];
uint8_t prevState = IN_USE;
if (!sref.compare_exchange_strong(
prevState, IN_SHUTDOWN, std::memory_order_relaxed)) {
......@@ -133,12 +181,10 @@ void ShutdownSocketSet::shutdown(NetworkSocket fd, bool abortive) {
}
void ShutdownSocketSet::shutdownAll(bool abortive) {
for (int i = 0; i < maxFd_; ++i) {
auto& sref = data_[size_t(i)];
for (size_t p = 0; p < capacity_; ++p) {
auto& sref = data_[p];
if (sref.load(std::memory_order_relaxed) == IN_USE) {
shutdown(
NetworkSocket(static_cast<NetworkSocket::native_handle_type>(i)),
abortive);
shutdown(at(p), abortive);
}
}
}
......
......@@ -31,12 +31,12 @@ namespace folly {
class ShutdownSocketSet {
public:
/**
* Create a socket set that can handle file descriptors < maxFd.
* Create a socket set that can handle file descriptors within the capacity.
* The default value (256Ki) is high enough for just about all
* applications, even if you increased the number of file descriptors
* on your system.
*/
explicit ShutdownSocketSet(int maxFd = 1 << 18);
explicit ShutdownSocketSet(size_t capacity = 1 << 18);
ShutdownSocketSet(const ShutdownSocketSet&) = delete;
ShutdownSocketSet& operator=(const ShutdownSocketSet&) = delete;
......@@ -138,7 +138,7 @@ class ShutdownSocketSet {
}
};
const int maxFd_;
size_t const capacity_;
std::unique_ptr<std::atomic<uint8_t>[], Free> data_;
folly::File nullFile_;
};
......
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