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 @@ ...@@ -27,20 +27,65 @@
namespace folly { namespace folly {
ShutdownSocketSet::ShutdownSocketSet(int maxFd) using handle_t = NetworkSocket::native_handle_type;
: maxFd_(maxFd), 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>*>( 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) {} nullFile_("/dev/null", O_RDWR) {}
void ShutdownSocketSet::add(NetworkSocket fd) { void ShutdownSocketSet::add(NetworkSocket fd) {
// Silently ignore any fds >= maxFd_, very unlikely // Silently ignore any fds >= capacity_, very unlikely
DCHECK_NE(fd, NetworkSocket()); DCHECK_NE(fd, NetworkSocket());
if (fd.data >= maxFd_) { auto p = pos(fd);
if (p >= capacity_) {
return; return;
} }
auto& sref = data_[size_t(fd.data)]; auto& sref = data_[p];
uint8_t prevState = FREE; uint8_t prevState = FREE;
CHECK(sref.compare_exchange_strong( CHECK(sref.compare_exchange_strong(
prevState, IN_USE, std::memory_order_relaxed)) prevState, IN_USE, std::memory_order_relaxed))
...@@ -49,11 +94,12 @@ void ShutdownSocketSet::add(NetworkSocket fd) { ...@@ -49,11 +94,12 @@ void ShutdownSocketSet::add(NetworkSocket fd) {
void ShutdownSocketSet::remove(NetworkSocket fd) { void ShutdownSocketSet::remove(NetworkSocket fd) {
DCHECK_NE(fd, NetworkSocket()); DCHECK_NE(fd, NetworkSocket());
if (fd.data >= maxFd_) { auto p = pos(fd);
if (p >= capacity_) {
return; return;
} }
auto& sref = data_[size_t(fd.data)]; auto& sref = data_[p];
uint8_t prevState = 0; uint8_t prevState = 0;
prevState = sref.load(std::memory_order_relaxed); prevState = sref.load(std::memory_order_relaxed);
...@@ -73,11 +119,12 @@ void ShutdownSocketSet::remove(NetworkSocket fd) { ...@@ -73,11 +119,12 @@ void ShutdownSocketSet::remove(NetworkSocket fd) {
int ShutdownSocketSet::close(NetworkSocket fd) { int ShutdownSocketSet::close(NetworkSocket fd) {
DCHECK_NE(fd, NetworkSocket()); DCHECK_NE(fd, NetworkSocket());
if (fd.data >= maxFd_) { auto p = pos(fd);
if (p >= capacity_) {
return folly::closeNoInt(fd); 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 prevState = sref.load(std::memory_order_relaxed);
uint8_t newState = 0; uint8_t newState = 0;
...@@ -102,12 +149,13 @@ int ShutdownSocketSet::close(NetworkSocket fd) { ...@@ -102,12 +149,13 @@ int ShutdownSocketSet::close(NetworkSocket fd) {
void ShutdownSocketSet::shutdown(NetworkSocket fd, bool abortive) { void ShutdownSocketSet::shutdown(NetworkSocket fd, bool abortive) {
DCHECK_NE(fd, NetworkSocket()); DCHECK_NE(fd, NetworkSocket());
if (fd.data >= maxFd_) { auto p = pos(fd);
if (p >= capacity_) {
doShutdown(fd, abortive); doShutdown(fd, abortive);
return; return;
} }
auto& sref = data_[size_t(fd.data)]; auto& sref = data_[p];
uint8_t prevState = IN_USE; uint8_t prevState = IN_USE;
if (!sref.compare_exchange_strong( if (!sref.compare_exchange_strong(
prevState, IN_SHUTDOWN, std::memory_order_relaxed)) { prevState, IN_SHUTDOWN, std::memory_order_relaxed)) {
...@@ -133,12 +181,10 @@ void ShutdownSocketSet::shutdown(NetworkSocket fd, bool abortive) { ...@@ -133,12 +181,10 @@ void ShutdownSocketSet::shutdown(NetworkSocket fd, bool abortive) {
} }
void ShutdownSocketSet::shutdownAll(bool abortive) { void ShutdownSocketSet::shutdownAll(bool abortive) {
for (int i = 0; i < maxFd_; ++i) { for (size_t p = 0; p < capacity_; ++p) {
auto& sref = data_[size_t(i)]; auto& sref = data_[p];
if (sref.load(std::memory_order_relaxed) == IN_USE) { if (sref.load(std::memory_order_relaxed) == IN_USE) {
shutdown( shutdown(at(p), abortive);
NetworkSocket(static_cast<NetworkSocket::native_handle_type>(i)),
abortive);
} }
} }
} }
......
...@@ -31,12 +31,12 @@ namespace folly { ...@@ -31,12 +31,12 @@ namespace folly {
class ShutdownSocketSet { class ShutdownSocketSet {
public: 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 * The default value (256Ki) is high enough for just about all
* applications, even if you increased the number of file descriptors * applications, even if you increased the number of file descriptors
* on your system. * on your system.
*/ */
explicit ShutdownSocketSet(int maxFd = 1 << 18); explicit ShutdownSocketSet(size_t capacity = 1 << 18);
ShutdownSocketSet(const ShutdownSocketSet&) = delete; ShutdownSocketSet(const ShutdownSocketSet&) = delete;
ShutdownSocketSet& operator=(const ShutdownSocketSet&) = delete; ShutdownSocketSet& operator=(const ShutdownSocketSet&) = delete;
...@@ -138,7 +138,7 @@ class ShutdownSocketSet { ...@@ -138,7 +138,7 @@ class ShutdownSocketSet {
} }
}; };
const int maxFd_; size_t const capacity_;
std::unique_ptr<std::atomic<uint8_t>[], Free> data_; std::unique_ptr<std::atomic<uint8_t>[], Free> data_;
folly::File nullFile_; 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