folly-clib-20250713.1537: folly/folly/io/async/IoUringBase.h
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* 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.
*/
#pragma once
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <folly/io/IOBuf.h>
#include <folly/io/async/DelayedDestruction.h>
struct io_uring_sqe;
struct io_uring_cqe;
namespace folly {
class IoUringBackend;
class EventBase;
struct IoSqeBase
: boost::intrusive::list_base_hook<
boost::intrusive::link_mode<boost::intrusive::auto_unlink>> {
enum class Type {
Unknown,
Read,
Write,
Open,
Close,
Connect,
Cancel,
};
IoSqeBase() : IoSqeBase(Type::Unknown) {}
explicit IoSqeBase(Type type) : type_(type) {}
// use raw addresses, so disallow copy/move
IoSqeBase(IoSqeBase&&) = delete;
IoSqeBase(const IoSqeBase&) = delete;
IoSqeBase& operator=(IoSqeBase&&) = delete;
IoSqeBase& operator=(const IoSqeBase&) = delete;
virtual ~IoSqeBase() = default;
virtual void processSubmit(struct io_uring_sqe* sqe) noexcept = 0;
virtual void callback(const io_uring_cqe* cqe) noexcept = 0;
virtual void callbackCancelled(const io_uring_cqe* cqe) noexcept = 0;
IoSqeBase::Type type() const { return type_; }
bool inFlight() const { return inFlight_; }
bool cancelled() const { return cancelled_; }
void markCancelled() { cancelled_ = true; }
void setEventBase(EventBase* evb) { evb_ = evb; }
protected:
// This is used if you want to prepare this sqe for reuse, but will manage the
// lifetime. For example for zerocopy send, you might want to reuse the sqe
// but still have a notification inbound.
void prepareForReuse() { internalUnmarkInflight(); }
private:
friend class IoUringBackend;
void internalSubmit(struct io_uring_sqe* sqe) noexcept;
void internalCallback(const io_uring_cqe* cqe) noexcept;
void internalUnmarkInflight() { inFlight_ = false; }
bool inFlight_ = false;
bool cancelled_ = false;
EventBase* evb_ = nullptr;
Type type_;
};
class IoUringBufferProviderBase {
protected:
uint16_t const gid_;
size_t const sizePerBuffer_;
public:
struct Deleter {
void operator()(IoUringBufferProviderBase* base) {
if (base) {
base->destroy();
}
}
};
using UniquePtr = std::unique_ptr<IoUringBufferProviderBase, Deleter>;
explicit IoUringBufferProviderBase(uint16_t gid, size_t sizePerBuffer)
: gid_(gid), sizePerBuffer_(sizePerBuffer) {}
virtual ~IoUringBufferProviderBase() = default;
IoUringBufferProviderBase(IoUringBufferProviderBase&&) = delete;
IoUringBufferProviderBase(IoUringBufferProviderBase const&) = delete;
IoUringBufferProviderBase& operator=(IoUringBufferProviderBase&&) = delete;
IoUringBufferProviderBase& operator=(IoUringBufferProviderBase const&) =
delete;
size_t sizePerBuffer() const { return sizePerBuffer_; }
uint16_t gid() const { return gid_; }
virtual uint32_t count() const noexcept = 0;
virtual void unusedBuf(uint16_t i) noexcept = 0;
virtual std::unique_ptr<IOBuf> getIoBuf(
uint16_t i, size_t length) noexcept = 0;
virtual void enobuf() noexcept = 0;
virtual bool available() const noexcept = 0;
virtual void destroy() noexcept = 0;
};
struct IoUringFdRegistrationRecord
: public boost::intrusive::slist_base_hook<
boost::intrusive::cache_last<false>> {
int count_{0};
int fd_{-1};
int idx_{0};
};
} // namespace folly