create
This commit is contained in:
49
Pods/gRPC-Core/include/grpc/event_engine/endpoint_config.h
generated
Normal file
49
Pods/gRPC-Core/include/grpc/event_engine/endpoint_config.h
generated
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// 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.
|
||||
#ifndef GRPC_EVENT_ENGINE_ENDPOINT_CONFIG_H
|
||||
#define GRPC_EVENT_ENGINE_ENDPOINT_CONFIG_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
|
||||
namespace grpc_event_engine {
|
||||
namespace experimental {
|
||||
|
||||
/// Collection of parameters used to configure client and server endpoints. The
|
||||
/// \a EndpointConfig maps string-valued keys to values of type int,
|
||||
/// string_view, or void pointer. Each EventEngine implementation should
|
||||
/// document its set of supported configuration options.
|
||||
class EndpointConfig {
|
||||
public:
|
||||
virtual ~EndpointConfig() = default;
|
||||
// If the key points to an integer config, an integer value gets returned.
|
||||
// Otherwise it returns an absl::nullopt_t
|
||||
virtual absl::optional<int> GetInt(absl::string_view key) const = 0;
|
||||
// If the key points to an string config, an string value gets returned.
|
||||
// Otherwise it returns an absl::nullopt_t
|
||||
virtual absl::optional<absl::string_view> GetString(
|
||||
absl::string_view key) const = 0;
|
||||
// If the key points to an void* config, a void* pointer value gets returned.
|
||||
// Otherwise it returns nullptr
|
||||
virtual void* GetVoidPointer(absl::string_view key) const = 0;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_ENDPOINT_CONFIG_H
|
||||
500
Pods/gRPC-Core/include/grpc/event_engine/event_engine.h
generated
Normal file
500
Pods/gRPC-Core/include/grpc/event_engine/event_engine.h
generated
Normal file
@@ -0,0 +1,500 @@
|
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// 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.
|
||||
#ifndef GRPC_EVENT_ENGINE_EVENT_ENGINE_H
|
||||
#define GRPC_EVENT_ENGINE_EVENT_ENGINE_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
|
||||
#include <grpc/event_engine/endpoint_config.h>
|
||||
#include <grpc/event_engine/extensible.h>
|
||||
#include <grpc/event_engine/memory_allocator.h>
|
||||
#include <grpc/event_engine/port.h>
|
||||
#include <grpc/event_engine/slice_buffer.h>
|
||||
|
||||
// TODO(vigneshbabu): Define the Endpoint::Write metrics collection system
|
||||
namespace grpc_event_engine {
|
||||
namespace experimental {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The EventEngine Interface
|
||||
///
|
||||
/// Overview
|
||||
/// --------
|
||||
///
|
||||
/// The EventEngine encapsulates all platform-specific behaviors related to low
|
||||
/// level network I/O, timers, asynchronous execution, and DNS resolution.
|
||||
///
|
||||
/// This interface allows developers to provide their own event management and
|
||||
/// network stacks. Motivating uses cases for supporting custom EventEngines
|
||||
/// include the ability to hook into external event loops, and using different
|
||||
/// EventEngine instances for each channel to better insulate network I/O and
|
||||
/// callback processing from other channels.
|
||||
///
|
||||
/// A default cross-platform EventEngine instance is provided by gRPC.
|
||||
///
|
||||
/// Lifespan and Ownership
|
||||
/// ----------------------
|
||||
///
|
||||
/// gRPC takes shared ownership of EventEngines via std::shared_ptrs to ensure
|
||||
/// that the engines remain available until they are no longer needed. Depending
|
||||
/// on the use case, engines may live until gRPC is shut down.
|
||||
///
|
||||
/// EXAMPLE USAGE (Not yet implemented)
|
||||
///
|
||||
/// Custom EventEngines can be specified per channel, and allow configuration
|
||||
/// for both clients and servers. To set a custom EventEngine for a client
|
||||
/// channel, you can do something like the following:
|
||||
///
|
||||
/// ChannelArguments args;
|
||||
/// std::shared_ptr<EventEngine> engine = std::make_shared<MyEngine>(...);
|
||||
/// args.SetEventEngine(engine);
|
||||
/// MyAppClient client(grpc::CreateCustomChannel(
|
||||
/// "localhost:50051", grpc::InsecureChannelCredentials(), args));
|
||||
///
|
||||
/// A gRPC server can use a custom EventEngine by calling the
|
||||
/// ServerBuilder::SetEventEngine method:
|
||||
///
|
||||
/// ServerBuilder builder;
|
||||
/// std::shared_ptr<EventEngine> engine = std::make_shared<MyEngine>(...);
|
||||
/// builder.SetEventEngine(engine);
|
||||
/// std::unique_ptr<Server> server(builder.BuildAndStart());
|
||||
/// server->Wait();
|
||||
///
|
||||
///
|
||||
/// Blocking EventEngine Callbacks
|
||||
/// ------------------------------
|
||||
///
|
||||
/// Doing blocking work in EventEngine callbacks is generally not advisable.
|
||||
/// While gRPC's default EventEngine implementations have some capacity to scale
|
||||
/// their thread pools to avoid starvation, this is not an instantaneous
|
||||
/// process. Further, user-provided EventEngines may not be optimized to handle
|
||||
/// excessive blocking work at all.
|
||||
///
|
||||
/// *Best Practice* : Occasional blocking work may be fine, but we do not
|
||||
/// recommend running a mostly blocking workload in EventEngine threads.
|
||||
///
|
||||
///
|
||||
/// Thread-safety guarantees
|
||||
/// ------------------------
|
||||
///
|
||||
/// All EventEngine methods are guaranteed to be thread-safe, no external
|
||||
/// synchronization is required to call any EventEngine method. Please note that
|
||||
/// this does not apply to application callbacks, which may be run concurrently;
|
||||
/// application state synchronization must be managed by the application.
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class EventEngine : public std::enable_shared_from_this<EventEngine>,
|
||||
public Extensible {
|
||||
public:
|
||||
/// A duration between two events.
|
||||
///
|
||||
/// Throughout the EventEngine API durations are used to express how long
|
||||
/// until an action should be performed.
|
||||
using Duration = std::chrono::duration<int64_t, std::nano>;
|
||||
/// A custom closure type for EventEngine task execution.
|
||||
///
|
||||
/// Throughout the EventEngine API, \a Closure ownership is retained by the
|
||||
/// caller - the EventEngine will never delete a Closure, and upon
|
||||
/// cancellation, the EventEngine will simply forget the Closure exists. The
|
||||
/// caller is responsible for all necessary cleanup.
|
||||
|
||||
class Closure {
|
||||
public:
|
||||
Closure() = default;
|
||||
// Closure's are an interface, and thus non-copyable.
|
||||
Closure(const Closure&) = delete;
|
||||
Closure& operator=(const Closure&) = delete;
|
||||
// Polymorphic type => virtual destructor
|
||||
virtual ~Closure() = default;
|
||||
// Run the contained code.
|
||||
virtual void Run() = 0;
|
||||
};
|
||||
/// Represents a scheduled task.
|
||||
///
|
||||
/// \a TaskHandles are returned by \a Run* methods, and can be given to the
|
||||
/// \a Cancel method.
|
||||
struct TaskHandle {
|
||||
intptr_t keys[2];
|
||||
static const GRPC_DLL TaskHandle kInvalid;
|
||||
friend bool operator==(const TaskHandle& lhs, const TaskHandle& rhs);
|
||||
friend bool operator!=(const TaskHandle& lhs, const TaskHandle& rhs);
|
||||
};
|
||||
/// A handle to a cancellable connection attempt.
|
||||
///
|
||||
/// Returned by \a Connect, and can be passed to \a CancelConnect.
|
||||
struct ConnectionHandle {
|
||||
intptr_t keys[2];
|
||||
static const GRPC_DLL ConnectionHandle kInvalid;
|
||||
friend bool operator==(const ConnectionHandle& lhs,
|
||||
const ConnectionHandle& rhs);
|
||||
friend bool operator!=(const ConnectionHandle& lhs,
|
||||
const ConnectionHandle& rhs);
|
||||
};
|
||||
/// Thin wrapper around a platform-specific sockaddr type. A sockaddr struct
|
||||
/// exists on all platforms that gRPC supports.
|
||||
///
|
||||
/// Platforms are expected to provide definitions for:
|
||||
/// * sockaddr
|
||||
/// * sockaddr_in
|
||||
/// * sockaddr_in6
|
||||
class ResolvedAddress {
|
||||
public:
|
||||
static constexpr socklen_t MAX_SIZE_BYTES = 128;
|
||||
|
||||
ResolvedAddress(const sockaddr* address, socklen_t size);
|
||||
ResolvedAddress() = default;
|
||||
ResolvedAddress(const ResolvedAddress&) = default;
|
||||
const struct sockaddr* address() const;
|
||||
socklen_t size() const;
|
||||
|
||||
private:
|
||||
char address_[MAX_SIZE_BYTES] = {};
|
||||
socklen_t size_ = 0;
|
||||
};
|
||||
|
||||
/// One end of a connection between a gRPC client and server. Endpoints are
|
||||
/// created when connections are established, and Endpoint operations are
|
||||
/// gRPC's primary means of communication.
|
||||
///
|
||||
/// Endpoints must use the provided MemoryAllocator for all data buffer memory
|
||||
/// allocations. gRPC allows applications to set memory constraints per
|
||||
/// Channel or Server, and the implementation depends on all dynamic memory
|
||||
/// allocation being handled by the quota system.
|
||||
class Endpoint : public Extensible {
|
||||
public:
|
||||
/// Shuts down all connections and invokes all pending read or write
|
||||
/// callbacks with an error status.
|
||||
virtual ~Endpoint() = default;
|
||||
/// A struct representing optional arguments that may be provided to an
|
||||
/// EventEngine Endpoint Read API call.
|
||||
///
|
||||
/// Passed as argument to an Endpoint \a Read
|
||||
struct ReadArgs {
|
||||
// A suggestion to the endpoint implementation to read at-least the
|
||||
// specified number of bytes over the network connection before marking
|
||||
// the endpoint read operation as complete. gRPC may use this argument
|
||||
// to minimize the number of endpoint read API calls over the lifetime
|
||||
// of a connection.
|
||||
int64_t read_hint_bytes;
|
||||
};
|
||||
/// Reads data from the Endpoint.
|
||||
///
|
||||
/// When data is available on the connection, that data is moved into the
|
||||
/// \a buffer. If the read succeeds immediately, it returns true and the \a
|
||||
/// on_read callback is not executed. Otherwise it returns false and the \a
|
||||
/// on_read callback executes asynchronously when the read completes. The
|
||||
/// caller must ensure that the callback has access to the buffer when it
|
||||
/// executes. Ownership of the buffer is not transferred. Valid slices *may*
|
||||
/// be placed into the buffer even if the callback is invoked with a non-OK
|
||||
/// Status.
|
||||
///
|
||||
/// There can be at most one outstanding read per Endpoint at any given
|
||||
/// time. An outstanding read is one in which the \a on_read callback has
|
||||
/// not yet been executed for some previous call to \a Read. If an attempt
|
||||
/// is made to call \a Read while a previous read is still outstanding, the
|
||||
/// \a EventEngine must abort.
|
||||
///
|
||||
/// For failed read operations, implementations should pass the appropriate
|
||||
/// statuses to \a on_read. For example, callbacks might expect to receive
|
||||
/// CANCELLED on endpoint shutdown.
|
||||
virtual bool Read(absl::AnyInvocable<void(absl::Status)> on_read,
|
||||
SliceBuffer* buffer, const ReadArgs* args) = 0;
|
||||
/// A struct representing optional arguments that may be provided to an
|
||||
/// EventEngine Endpoint Write API call.
|
||||
///
|
||||
/// Passed as argument to an Endpoint \a Write
|
||||
struct WriteArgs {
|
||||
// Represents private information that may be passed by gRPC for
|
||||
// select endpoints expected to be used only within google.
|
||||
void* google_specific = nullptr;
|
||||
// A suggestion to the endpoint implementation to group data to be written
|
||||
// into frames of the specified max_frame_size. gRPC may use this
|
||||
// argument to dynamically control the max sizes of frames sent to a
|
||||
// receiver in response to high receiver memory pressure.
|
||||
int64_t max_frame_size;
|
||||
};
|
||||
/// Writes data out on the connection.
|
||||
///
|
||||
/// If the write succeeds immediately, it returns true and the
|
||||
/// \a on_writable callback is not executed. Otherwise it returns false and
|
||||
/// the \a on_writable callback is called asynchronously when the connection
|
||||
/// is ready for more data. The Slices within the \a data buffer may be
|
||||
/// mutated at will by the Endpoint until \a on_writable is called. The \a
|
||||
/// data SliceBuffer will remain valid after calling \a Write, but its state
|
||||
/// is otherwise undefined. All bytes in \a data must have been written
|
||||
/// before calling \a on_writable unless an error has occurred.
|
||||
///
|
||||
/// There can be at most one outstanding write per Endpoint at any given
|
||||
/// time. An outstanding write is one in which the \a on_writable callback
|
||||
/// has not yet been executed for some previous call to \a Write. If an
|
||||
/// attempt is made to call \a Write while a previous write is still
|
||||
/// outstanding, the \a EventEngine must abort.
|
||||
///
|
||||
/// For failed write operations, implementations should pass the appropriate
|
||||
/// statuses to \a on_writable. For example, callbacks might expect to
|
||||
/// receive CANCELLED on endpoint shutdown.
|
||||
virtual bool Write(absl::AnyInvocable<void(absl::Status)> on_writable,
|
||||
SliceBuffer* data, const WriteArgs* args) = 0;
|
||||
/// Returns an address in the format described in DNSResolver. The returned
|
||||
/// values are expected to remain valid for the life of the Endpoint.
|
||||
virtual const ResolvedAddress& GetPeerAddress() const = 0;
|
||||
virtual const ResolvedAddress& GetLocalAddress() const = 0;
|
||||
};
|
||||
|
||||
/// Called when a new connection is established.
|
||||
///
|
||||
/// If the connection attempt was not successful, implementations should pass
|
||||
/// the appropriate statuses to this callback. For example, callbacks might
|
||||
/// expect to receive DEADLINE_EXCEEDED statuses when appropriate, or
|
||||
/// CANCELLED statuses on EventEngine shutdown.
|
||||
using OnConnectCallback =
|
||||
absl::AnyInvocable<void(absl::StatusOr<std::unique_ptr<Endpoint>>)>;
|
||||
|
||||
/// Listens for incoming connection requests from gRPC clients and initiates
|
||||
/// request processing once connections are established.
|
||||
class Listener : public Extensible {
|
||||
public:
|
||||
/// Called when the listener has accepted a new client connection.
|
||||
using AcceptCallback = absl::AnyInvocable<void(
|
||||
std::unique_ptr<Endpoint>, MemoryAllocator memory_allocator)>;
|
||||
virtual ~Listener() = default;
|
||||
/// Bind an address/port to this Listener.
|
||||
///
|
||||
/// It is expected that multiple addresses/ports can be bound to this
|
||||
/// Listener before Listener::Start has been called. Returns either the
|
||||
/// bound port or an appropriate error status.
|
||||
virtual absl::StatusOr<int> Bind(const ResolvedAddress& addr) = 0;
|
||||
virtual absl::Status Start() = 0;
|
||||
};
|
||||
|
||||
/// Factory method to create a network listener / server.
|
||||
///
|
||||
/// Once a \a Listener is created and started, the \a on_accept callback will
|
||||
/// be called once asynchronously for each established connection. This method
|
||||
/// may return a non-OK status immediately if an error was encountered in any
|
||||
/// synchronous steps required to create the Listener. In this case,
|
||||
/// \a on_shutdown will never be called.
|
||||
///
|
||||
/// If this method returns a Listener, then \a on_shutdown will be invoked
|
||||
/// exactly once when the Listener is shut down, and only after all
|
||||
/// \a on_accept callbacks have finished executing. The status passed to it
|
||||
/// will indicate if there was a problem during shutdown.
|
||||
///
|
||||
/// The provided \a MemoryAllocatorFactory is used to create \a
|
||||
/// MemoryAllocators for Endpoint construction.
|
||||
virtual absl::StatusOr<std::unique_ptr<Listener>> CreateListener(
|
||||
Listener::AcceptCallback on_accept,
|
||||
absl::AnyInvocable<void(absl::Status)> on_shutdown,
|
||||
const EndpointConfig& config,
|
||||
std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory) = 0;
|
||||
/// Creates a client network connection to a remote network listener.
|
||||
///
|
||||
/// Even in the event of an error, it is expected that the \a on_connect
|
||||
/// callback will be asynchronously executed exactly once by the EventEngine.
|
||||
/// A connection attempt can be cancelled using the \a CancelConnect method.
|
||||
///
|
||||
/// Implementation Note: it is important that the \a memory_allocator be used
|
||||
/// for all read/write buffer allocations in the EventEngine implementation.
|
||||
/// This allows gRPC's \a ResourceQuota system to monitor and control memory
|
||||
/// usage with graceful degradation mechanisms. Please see the \a
|
||||
/// MemoryAllocator API for more information.
|
||||
virtual ConnectionHandle Connect(OnConnectCallback on_connect,
|
||||
const ResolvedAddress& addr,
|
||||
const EndpointConfig& args,
|
||||
MemoryAllocator memory_allocator,
|
||||
Duration timeout) = 0;
|
||||
|
||||
/// Request cancellation of a connection attempt.
|
||||
///
|
||||
/// If the associated connection has already been completed, it will not be
|
||||
/// cancelled, and this method will return false.
|
||||
///
|
||||
/// If the associated connection has not been completed, it will be cancelled,
|
||||
/// and this method will return true. The \a OnConnectCallback will not be
|
||||
/// called, and \a on_connect will be destroyed before this method returns.
|
||||
virtual bool CancelConnect(ConnectionHandle handle) = 0;
|
||||
/// Provides asynchronous resolution.
|
||||
///
|
||||
/// This object has a destruction-is-cancellation semantic.
|
||||
/// Implementations should make sure that all pending requests are cancelled
|
||||
/// when the object is destroyed and all pending callbacks will be called
|
||||
/// shortly. If cancellation races with request completion, implementations
|
||||
/// may choose to either cancel or satisfy the request.
|
||||
class DNSResolver {
|
||||
public:
|
||||
/// Optional configuration for DNSResolvers.
|
||||
struct ResolverOptions {
|
||||
/// If empty, default DNS servers will be used.
|
||||
/// Must be in the "IP:port" format as described in naming.md.
|
||||
std::string dns_server;
|
||||
};
|
||||
/// DNS SRV record type.
|
||||
struct SRVRecord {
|
||||
std::string host;
|
||||
int port = 0;
|
||||
int priority = 0;
|
||||
int weight = 0;
|
||||
};
|
||||
/// Called with the collection of sockaddrs that were resolved from a given
|
||||
/// target address.
|
||||
using LookupHostnameCallback =
|
||||
absl::AnyInvocable<void(absl::StatusOr<std::vector<ResolvedAddress>>)>;
|
||||
/// Called with a collection of SRV records.
|
||||
using LookupSRVCallback =
|
||||
absl::AnyInvocable<void(absl::StatusOr<std::vector<SRVRecord>>)>;
|
||||
/// Called with the result of a TXT record lookup
|
||||
using LookupTXTCallback =
|
||||
absl::AnyInvocable<void(absl::StatusOr<std::vector<std::string>>)>;
|
||||
|
||||
virtual ~DNSResolver() = default;
|
||||
|
||||
/// Asynchronously resolve an address.
|
||||
///
|
||||
/// \a default_port may be a non-numeric named service port, and will only
|
||||
/// be used if \a address does not already contain a port component.
|
||||
///
|
||||
/// When the lookup is complete or cancelled, the \a on_resolve callback
|
||||
/// will be invoked with a status indicating the success or failure of the
|
||||
/// lookup. Implementations should pass the appropriate statuses to the
|
||||
/// callback. For example, callbacks might expect to receive CANCELLED or
|
||||
/// NOT_FOUND.
|
||||
virtual void LookupHostname(LookupHostnameCallback on_resolve,
|
||||
absl::string_view name,
|
||||
absl::string_view default_port) = 0;
|
||||
/// Asynchronously perform an SRV record lookup.
|
||||
///
|
||||
/// \a on_resolve has the same meaning and expectations as \a
|
||||
/// LookupHostname's \a on_resolve callback.
|
||||
virtual void LookupSRV(LookupSRVCallback on_resolve,
|
||||
absl::string_view name) = 0;
|
||||
/// Asynchronously perform a TXT record lookup.
|
||||
///
|
||||
/// \a on_resolve has the same meaning and expectations as \a
|
||||
/// LookupHostname's \a on_resolve callback.
|
||||
virtual void LookupTXT(LookupTXTCallback on_resolve,
|
||||
absl::string_view name) = 0;
|
||||
};
|
||||
|
||||
/// At time of destruction, the EventEngine must have no active
|
||||
/// responsibilities. EventEngine users (applications) are responsible for
|
||||
/// cancelling all tasks and DNS lookups, shutting down listeners and
|
||||
/// endpoints, prior to EventEngine destruction. If there are any outstanding
|
||||
/// tasks, any running listeners, etc. at time of EventEngine destruction,
|
||||
/// that is an invalid use of the API, and it will result in undefined
|
||||
/// behavior.
|
||||
virtual ~EventEngine() = default;
|
||||
|
||||
// TODO(nnoble): consider whether we can remove this method before we
|
||||
// de-experimentalize this API.
|
||||
virtual bool IsWorkerThread() = 0;
|
||||
|
||||
/// Creates and returns an instance of a DNSResolver, optionally configured by
|
||||
/// the \a options struct. This method may return a non-OK status if an error
|
||||
/// occurred when creating the DNSResolver. If the caller requests a custom
|
||||
/// DNS server, and the EventEngine implementation does not support it, this
|
||||
/// must return an error.
|
||||
virtual absl::StatusOr<std::unique_ptr<DNSResolver>> GetDNSResolver(
|
||||
const DNSResolver::ResolverOptions& options) = 0;
|
||||
|
||||
/// Asynchronously executes a task as soon as possible.
|
||||
///
|
||||
/// \a Closures passed to \a Run cannot be cancelled. The \a closure will not
|
||||
/// be deleted after it has been run, ownership remains with the caller.
|
||||
///
|
||||
/// Implementations must not execute the closure in the calling thread before
|
||||
/// \a Run returns. For example, if the caller must release a lock before the
|
||||
/// closure can proceed, running the closure immediately would cause a
|
||||
/// deadlock.
|
||||
virtual void Run(Closure* closure) = 0;
|
||||
/// Asynchronously executes a task as soon as possible.
|
||||
///
|
||||
/// \a Closures passed to \a Run cannot be cancelled. Unlike the overloaded \a
|
||||
/// Closure alternative, the absl::AnyInvocable version's \a closure will be
|
||||
/// deleted by the EventEngine after the closure has been run.
|
||||
///
|
||||
/// This version of \a Run may be less performant than the \a Closure version
|
||||
/// in some scenarios. This overload is useful in situations where performance
|
||||
/// is not a critical concern.
|
||||
///
|
||||
/// Implementations must not execute the closure in the calling thread before
|
||||
/// \a Run returns.
|
||||
virtual void Run(absl::AnyInvocable<void()> closure) = 0;
|
||||
/// Synonymous with scheduling an alarm to run after duration \a when.
|
||||
///
|
||||
/// The \a closure will execute when time \a when arrives unless it has been
|
||||
/// cancelled via the \a Cancel method. If cancelled, the closure will not be
|
||||
/// run, nor will it be deleted. Ownership remains with the caller.
|
||||
///
|
||||
/// Implementations must not execute the closure in the calling thread before
|
||||
/// \a RunAfter returns.
|
||||
virtual TaskHandle RunAfter(Duration when, Closure* closure) = 0;
|
||||
/// Synonymous with scheduling an alarm to run after duration \a when.
|
||||
///
|
||||
/// The \a closure will execute when time \a when arrives unless it has been
|
||||
/// cancelled via the \a Cancel method. If cancelled, the closure will not be
|
||||
/// run. Unlike the overloaded \a Closure alternative, the absl::AnyInvocable
|
||||
/// version's \a closure will be deleted by the EventEngine after the closure
|
||||
/// has been run, or upon cancellation.
|
||||
///
|
||||
/// This version of \a RunAfter may be less performant than the \a Closure
|
||||
/// version in some scenarios. This overload is useful in situations where
|
||||
/// performance is not a critical concern.
|
||||
///
|
||||
/// Implementations must not execute the closure in the calling thread before
|
||||
/// \a RunAfter returns.
|
||||
virtual TaskHandle RunAfter(Duration when,
|
||||
absl::AnyInvocable<void()> closure) = 0;
|
||||
/// Request cancellation of a task.
|
||||
///
|
||||
/// If the associated closure cannot be cancelled for any reason, this
|
||||
/// function will return false.
|
||||
///
|
||||
/// If the associated closure can be cancelled, the associated callback will
|
||||
/// never be run, and this method will return true. If the callback type was
|
||||
/// an absl::AnyInvocable, it will be destroyed before the method returns.
|
||||
virtual bool Cancel(TaskHandle handle) = 0;
|
||||
};
|
||||
|
||||
/// Replace gRPC's default EventEngine factory.
|
||||
///
|
||||
/// Applications may call \a SetEventEngineFactory at any time to replace the
|
||||
/// default factory used within gRPC. EventEngines will be created when
|
||||
/// necessary, when they are otherwise not provided by the application.
|
||||
///
|
||||
/// To be certain that none of the gRPC-provided built-in EventEngines are
|
||||
/// created, applications must set a custom EventEngine factory method *before*
|
||||
/// grpc is initialized.
|
||||
void SetEventEngineFactory(
|
||||
absl::AnyInvocable<std::unique_ptr<EventEngine>()> factory);
|
||||
|
||||
/// Reset gRPC's EventEngine factory to the built-in default.
|
||||
///
|
||||
/// Applications that have called \a SetEventEngineFactory can remove their
|
||||
/// custom factory using this method. The built-in EventEngine factories will be
|
||||
/// used going forward. This has no affect on any EventEngines that were created
|
||||
/// using the previous factories.
|
||||
void EventEngineFactoryReset();
|
||||
/// Create an EventEngine using the default factory.
|
||||
std::unique_ptr<EventEngine> CreateEventEngine();
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_EVENT_ENGINE_H
|
||||
68
Pods/gRPC-Core/include/grpc/event_engine/extensible.h
generated
Normal file
68
Pods/gRPC-Core/include/grpc/event_engine/extensible.h
generated
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2024 The gRPC Authors
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef GRPC_EVENT_ENGINE_EXTENSIBLE_H
|
||||
#define GRPC_EVENT_ENGINE_EXTENSIBLE_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace grpc_event_engine {
|
||||
namespace experimental {
|
||||
|
||||
class Extensible {
|
||||
public:
|
||||
/// A method which allows users to query whether an implementation supports a
|
||||
/// specified extension. The name of the extension is provided as an input.
|
||||
///
|
||||
/// An extension could be any type with a unique string id. Each extension may
|
||||
/// support additional capabilities and if the implementation supports the
|
||||
/// queried extension, it should return a valid pointer to the extension type.
|
||||
///
|
||||
/// E.g., use case of an EventEngine::Endpoint supporting a custom extension.
|
||||
///
|
||||
/// class CustomEndpointExtension {
|
||||
/// public:
|
||||
/// static std::string EndpointExtensionName() {
|
||||
/// return "my.namespace.extension_name";
|
||||
/// }
|
||||
/// virtual void Process() = 0;
|
||||
/// }
|
||||
///
|
||||
/// class CustomEndpoint :
|
||||
/// public EventEngine::Endpoint, public CustomEndpointExtension {
|
||||
/// public:
|
||||
/// void* QueryExtension(absl::string_view id) override {
|
||||
/// if (id == CustomEndpointExtension::EndpointExtensionName()) {
|
||||
/// return static_cast<CustomEndpointExtension*>(this);
|
||||
/// }
|
||||
/// return nullptr;
|
||||
/// }
|
||||
/// void Process() override { ... }
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// auto endpoint =
|
||||
/// static_cast<CustomEndpointExtension*>(endpoint->QueryExtension(
|
||||
/// CustomEndpointExtension::EndpointExtensionName()));
|
||||
/// if (endpoint != nullptr) endpoint->Process();
|
||||
///
|
||||
virtual void* QueryExtension(absl::string_view /*id*/) { return nullptr; }
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_EXTENSIBLE_H
|
||||
74
Pods/gRPC-Core/include/grpc/event_engine/internal/memory_allocator_impl.h
generated
Normal file
74
Pods/gRPC-Core/include/grpc/event_engine/internal/memory_allocator_impl.h
generated
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// 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.
|
||||
#ifndef GRPC_EVENT_ENGINE_INTERNAL_MEMORY_ALLOCATOR_IMPL_H
|
||||
#define GRPC_EVENT_ENGINE_INTERNAL_MEMORY_ALLOCATOR_IMPL_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <grpc/event_engine/memory_request.h>
|
||||
#include <grpc/slice.h>
|
||||
|
||||
namespace grpc_event_engine {
|
||||
namespace experimental {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/// Underlying memory allocation interface.
|
||||
/// This is an internal interface, not intended to be used by users.
|
||||
/// Its interface is subject to change at any time.
|
||||
class MemoryAllocatorImpl
|
||||
: public std::enable_shared_from_this<MemoryAllocatorImpl> {
|
||||
public:
|
||||
MemoryAllocatorImpl() {}
|
||||
virtual ~MemoryAllocatorImpl() {}
|
||||
|
||||
MemoryAllocatorImpl(const MemoryAllocatorImpl&) = delete;
|
||||
MemoryAllocatorImpl& operator=(const MemoryAllocatorImpl&) = delete;
|
||||
|
||||
/// Reserve bytes from the quota.
|
||||
/// If we enter overcommit, reclamation will begin concurrently.
|
||||
/// Returns the number of bytes reserved.
|
||||
/// If MemoryRequest is invalid, this function will abort.
|
||||
/// If MemoryRequest is valid, this function is infallible, and will always
|
||||
/// succeed at reserving the some number of bytes between request.min() and
|
||||
/// request.max() inclusively.
|
||||
virtual size_t Reserve(MemoryRequest request) = 0;
|
||||
|
||||
/// Allocate a slice, using MemoryRequest to size the number of returned
|
||||
/// bytes. For a variable length request, check the returned slice length to
|
||||
/// verify how much memory was allocated. Takes care of reserving memory for
|
||||
/// any relevant control structures also.
|
||||
virtual grpc_slice MakeSlice(MemoryRequest request) = 0;
|
||||
|
||||
/// Release some bytes that were previously reserved.
|
||||
/// If more bytes are released than were reserved, we will have undefined
|
||||
/// behavior.
|
||||
virtual void Release(size_t n) = 0;
|
||||
|
||||
/// Shutdown this allocator.
|
||||
/// Further usage of Reserve() is undefined behavior.
|
||||
virtual void Shutdown() = 0;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_INTERNAL_MEMORY_ALLOCATOR_IMPL_H
|
||||
79
Pods/gRPC-Core/include/grpc/event_engine/internal/slice_cast.h
generated
Normal file
79
Pods/gRPC-Core/include/grpc/event_engine/internal/slice_cast.h
generated
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright 2022 gRPC authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef GRPC_EVENT_ENGINE_INTERNAL_SLICE_CAST_H
|
||||
#define GRPC_EVENT_ENGINE_INTERNAL_SLICE_CAST_H
|
||||
|
||||
namespace grpc_event_engine {
|
||||
namespace experimental {
|
||||
namespace internal {
|
||||
|
||||
// Opt-in trait class for slice conversions.
|
||||
// Declare a specialization of this class for any types that are compatible
|
||||
// with `SliceCast`. Both ways need to be declared (i.e. if
|
||||
// SliceCastable<A,B> exists, you should declare
|
||||
// SliceCastable<B,A> too).
|
||||
// The type has no members, it's just the existance of the specialization that
|
||||
// unlocks SliceCast usage for a type pair.
|
||||
template <typename Result, typename T>
|
||||
struct SliceCastable;
|
||||
|
||||
// This is strictly too wide, but consider all types to be SliceCast-able to
|
||||
// themselves.
|
||||
// Unfortunately this allows `const int& x = SliceCast<int>(x);` which is kind
|
||||
// of bogus.
|
||||
template <typename A>
|
||||
struct SliceCastable<A, A> {};
|
||||
|
||||
// Cast to `const Result&` from `const T&` without any runtime checks.
|
||||
// This is only valid if `sizeof(Result) == sizeof(T)`, and if `Result`, `T` are
|
||||
// opted in as compatible via `SliceCastable`.
|
||||
template <typename Result, typename T>
|
||||
const Result& SliceCast(const T& value, SliceCastable<Result, T> = {}) {
|
||||
// Insist upon sizes being equal to catch mismatches.
|
||||
// We assume if sizes are opted in and sizes are equal then yes, these two
|
||||
// types are expected to be layout compatible and actually appear to be.
|
||||
static_assert(sizeof(Result) == sizeof(T), "size mismatch");
|
||||
return reinterpret_cast<const Result&>(value);
|
||||
}
|
||||
|
||||
// Cast to `Result&` from `T&` without any runtime checks.
|
||||
// This is only valid if `sizeof(Result) == sizeof(T)`, and if `Result`, `T` are
|
||||
// opted in as compatible via `SliceCastable`.
|
||||
template <typename Result, typename T>
|
||||
Result& SliceCast(T& value, SliceCastable<Result, T> = {}) {
|
||||
// Insist upon sizes being equal to catch mismatches.
|
||||
// We assume if sizes are opted in and sizes are equal then yes, these two
|
||||
// types are expected to be layout compatible and actually appear to be.
|
||||
static_assert(sizeof(Result) == sizeof(T), "size mismatch");
|
||||
return reinterpret_cast<Result&>(value);
|
||||
}
|
||||
|
||||
// Cast to `Result&&` from `T&&` without any runtime checks.
|
||||
// This is only valid if `sizeof(Result) == sizeof(T)`, and if `Result`, `T` are
|
||||
// opted in as compatible via `SliceCastable`.
|
||||
template <typename Result, typename T>
|
||||
Result&& SliceCast(T&& value, SliceCastable<Result, T> = {}) {
|
||||
// Insist upon sizes being equal to catch mismatches.
|
||||
// We assume if sizes are opted in and sizes are equal then yes, these two
|
||||
// types are expected to be layout compatible and actually appear to be.
|
||||
static_assert(sizeof(Result) == sizeof(T), "size mismatch");
|
||||
return reinterpret_cast<Result&&>(value);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_INTERNAL_SLICE_CAST_H
|
||||
213
Pods/gRPC-Core/include/grpc/event_engine/memory_allocator.h
generated
Normal file
213
Pods/gRPC-Core/include/grpc/event_engine/memory_allocator.h
generated
Normal file
@@ -0,0 +1,213 @@
|
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// 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.
|
||||
#ifndef GRPC_EVENT_ENGINE_MEMORY_ALLOCATOR_H
|
||||
#define GRPC_EVENT_ENGINE_MEMORY_ALLOCATOR_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <stdlib.h> // for abort()
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <grpc/event_engine/internal/memory_allocator_impl.h>
|
||||
#include <grpc/slice.h>
|
||||
|
||||
namespace grpc_event_engine {
|
||||
namespace experimental {
|
||||
|
||||
// Tracks memory allocated by one system.
|
||||
// Is effectively a thin wrapper/smart pointer for a MemoryAllocatorImpl,
|
||||
// providing a convenient and stable API.
|
||||
class MemoryAllocator {
|
||||
public:
|
||||
/// Construct a MemoryAllocator given an internal::MemoryAllocatorImpl
|
||||
/// implementation. The constructed MemoryAllocator will call
|
||||
/// MemoryAllocatorImpl::Shutdown() upon destruction.
|
||||
explicit MemoryAllocator(
|
||||
std::shared_ptr<internal::MemoryAllocatorImpl> allocator)
|
||||
: allocator_(std::move(allocator)) {}
|
||||
// Construct an invalid MemoryAllocator.
|
||||
MemoryAllocator() : allocator_(nullptr) {}
|
||||
~MemoryAllocator() {
|
||||
if (allocator_ != nullptr) allocator_->Shutdown();
|
||||
}
|
||||
|
||||
MemoryAllocator(const MemoryAllocator&) = delete;
|
||||
MemoryAllocator& operator=(const MemoryAllocator&) = delete;
|
||||
|
||||
MemoryAllocator(MemoryAllocator&&) = default;
|
||||
MemoryAllocator& operator=(MemoryAllocator&&) = default;
|
||||
|
||||
/// Drop the underlying allocator and make this an empty object.
|
||||
/// The object will not be usable after this call unless it's a valid
|
||||
/// allocator is moved into it.
|
||||
void Reset() {
|
||||
auto a = std::move(allocator_);
|
||||
if (a != nullptr) a->Shutdown();
|
||||
}
|
||||
|
||||
/// Reserve bytes from the quota.
|
||||
/// If we enter overcommit, reclamation will begin concurrently.
|
||||
/// Returns the number of bytes reserved.
|
||||
size_t Reserve(MemoryRequest request) { return allocator_->Reserve(request); }
|
||||
|
||||
/// Release some bytes that were previously reserved.
|
||||
void Release(size_t n) { return allocator_->Release(n); }
|
||||
|
||||
//
|
||||
// The remainder of this type are helper functions implemented in terms of
|
||||
// Reserve/Release.
|
||||
//
|
||||
|
||||
/// An automatic releasing reservation of memory.
|
||||
class Reservation {
|
||||
public:
|
||||
Reservation() = default;
|
||||
Reservation(const Reservation&) = delete;
|
||||
Reservation& operator=(const Reservation&) = delete;
|
||||
Reservation(Reservation&&) = default;
|
||||
Reservation& operator=(Reservation&&) = default;
|
||||
~Reservation() {
|
||||
if (allocator_ != nullptr) allocator_->Release(size_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class MemoryAllocator;
|
||||
Reservation(std::shared_ptr<internal::MemoryAllocatorImpl> allocator,
|
||||
size_t size)
|
||||
: allocator_(std::move(allocator)), size_(size) {}
|
||||
|
||||
std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
|
||||
size_t size_ = 0;
|
||||
};
|
||||
|
||||
/// Reserve bytes from the quota and automatically release them when
|
||||
/// Reservation is destroyed.
|
||||
Reservation MakeReservation(MemoryRequest request) {
|
||||
return Reservation(allocator_, Reserve(request));
|
||||
}
|
||||
|
||||
/// Allocate a new object of type T, with constructor arguments.
|
||||
/// The returned type is wrapped, and upon destruction the reserved memory
|
||||
/// will be released to the allocator automatically. As such, T must have a
|
||||
/// virtual destructor so we can insert the necessary hook.
|
||||
template <typename T, typename... Args>
|
||||
typename std::enable_if<std::has_virtual_destructor<T>::value, T*>::type New(
|
||||
Args&&... args) {
|
||||
// Wrap T such that when it's destroyed, we can release memory back to the
|
||||
// allocator.
|
||||
class Wrapper final : public T {
|
||||
public:
|
||||
explicit Wrapper(std::shared_ptr<internal::MemoryAllocatorImpl> allocator,
|
||||
Args&&... args)
|
||||
: T(std::forward<Args>(args)...), allocator_(std::move(allocator)) {}
|
||||
~Wrapper() override { allocator_->Release(sizeof(*this)); }
|
||||
|
||||
private:
|
||||
const std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
|
||||
};
|
||||
Reserve(sizeof(Wrapper));
|
||||
return new Wrapper(allocator_, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// Construct a unique_ptr immediately.
|
||||
template <typename T, typename... Args>
|
||||
std::unique_ptr<T> MakeUnique(Args&&... args) {
|
||||
return std::unique_ptr<T>(New<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/// Allocate a slice, using MemoryRequest to size the number of returned
|
||||
/// bytes. For a variable length request, check the returned slice length to
|
||||
/// verify how much memory was allocated. Takes care of reserving memory for
|
||||
/// any relevant control structures also.
|
||||
grpc_slice MakeSlice(MemoryRequest request) {
|
||||
return allocator_->MakeSlice(request);
|
||||
}
|
||||
|
||||
/// A C++ allocator for containers of T.
|
||||
template <typename T>
|
||||
class Container {
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
/// Construct the allocator: \a underlying_allocator is borrowed, and must
|
||||
/// outlive this object.
|
||||
explicit Container(MemoryAllocator* underlying_allocator)
|
||||
: underlying_allocator_(underlying_allocator) {}
|
||||
template <typename U>
|
||||
explicit Container(const Container<U>& other)
|
||||
: underlying_allocator_(other.underlying_allocator()) {}
|
||||
|
||||
MemoryAllocator* underlying_allocator() const {
|
||||
return underlying_allocator_;
|
||||
}
|
||||
|
||||
T* allocate(size_t n) {
|
||||
underlying_allocator_->Reserve(n * sizeof(T));
|
||||
return static_cast<T*>(::operator new(n * sizeof(T)));
|
||||
}
|
||||
void deallocate(T* p, size_t n) {
|
||||
::operator delete(p);
|
||||
underlying_allocator_->Release(n * sizeof(T));
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryAllocator* underlying_allocator_;
|
||||
};
|
||||
|
||||
protected:
|
||||
/// Return a pointer to the underlying implementation.
|
||||
/// Note that the interface of said implementation is unstable and likely to
|
||||
/// change at any time.
|
||||
internal::MemoryAllocatorImpl* get_internal_impl_ptr() {
|
||||
return allocator_.get();
|
||||
}
|
||||
|
||||
const internal::MemoryAllocatorImpl* get_internal_impl_ptr() const {
|
||||
return allocator_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<internal::MemoryAllocatorImpl> allocator_;
|
||||
};
|
||||
|
||||
// Wrapper type around std::vector to make initialization against a
|
||||
// MemoryAllocator based container allocator easy.
|
||||
template <typename T>
|
||||
class Vector : public std::vector<T, MemoryAllocator::Container<T>> {
|
||||
public:
|
||||
explicit Vector(MemoryAllocator* allocator)
|
||||
: std::vector<T, MemoryAllocator::Container<T>>(
|
||||
MemoryAllocator::Container<T>(allocator)) {}
|
||||
};
|
||||
|
||||
class MemoryAllocatorFactory {
|
||||
public:
|
||||
virtual ~MemoryAllocatorFactory() = default;
|
||||
/// On Endpoint creation, call \a CreateMemoryAllocator to create a new
|
||||
/// allocator for the endpoint.
|
||||
/// \a name is used to label the memory allocator in debug logs.
|
||||
/// Typically we'll want to:
|
||||
/// auto allocator = factory->CreateMemoryAllocator(peer_address_string);
|
||||
/// auto* endpoint = allocator->New<MyEndpoint>(std::move(allocator), ...);
|
||||
virtual MemoryAllocator CreateMemoryAllocator(absl::string_view name) = 0;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_MEMORY_ALLOCATOR_H
|
||||
57
Pods/gRPC-Core/include/grpc/event_engine/memory_request.h
generated
Normal file
57
Pods/gRPC-Core/include/grpc/event_engine/memory_request.h
generated
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// 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.
|
||||
#ifndef GRPC_EVENT_ENGINE_MEMORY_REQUEST_H
|
||||
#define GRPC_EVENT_ENGINE_MEMORY_REQUEST_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace grpc_event_engine {
|
||||
namespace experimental {
|
||||
|
||||
/// Reservation request - how much memory do we want to allocate?
|
||||
class MemoryRequest {
|
||||
public:
|
||||
/// Request a fixed amount of memory.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
MemoryRequest(size_t n) : min_(n), max_(n) {}
|
||||
/// Request a range of memory.
|
||||
/// Requires: \a min <= \a max.
|
||||
/// Requires: \a max <= max_size()
|
||||
MemoryRequest(size_t min, size_t max) : min_(min), max_(max) {}
|
||||
|
||||
/// Maximum allowable request size - hard coded to 1GB.
|
||||
static constexpr size_t max_allowed_size() { return 1024 * 1024 * 1024; }
|
||||
|
||||
/// Increase the size by \a amount.
|
||||
/// Undefined behavior if min() + amount or max() + amount overflows.
|
||||
MemoryRequest Increase(size_t amount) const {
|
||||
return MemoryRequest(min_ + amount, max_ + amount);
|
||||
}
|
||||
|
||||
size_t min() const { return min_; }
|
||||
size_t max() const { return max_; }
|
||||
|
||||
private:
|
||||
size_t min_;
|
||||
size_t max_;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_MEMORY_REQUEST_H
|
||||
39
Pods/gRPC-Core/include/grpc/event_engine/port.h
generated
Normal file
39
Pods/gRPC-Core/include/grpc/event_engine/port.h
generated
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2021 The gRPC Authors
|
||||
//
|
||||
// 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.
|
||||
#ifndef GRPC_EVENT_ENGINE_PORT_H
|
||||
#define GRPC_EVENT_ENGINE_PORT_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
// Platform-specific sockaddr includes
|
||||
#if defined(GPR_ANDROID) || defined(GPR_LINUX) || defined(GPR_APPLE) || \
|
||||
defined(GPR_FREEBSD) || defined(GPR_OPENBSD) || defined(GPR_SOLARIS) || \
|
||||
defined(GPR_AIX) || defined(GPR_NACL) || defined(GPR_FUCHSIA) || \
|
||||
defined(GRPC_POSIX_SOCKET) || defined(GPR_NETBSD)
|
||||
#define GRPC_EVENT_ENGINE_POSIX
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#elif defined(GPR_WINDOWS)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
// must be included after the above
|
||||
#include <mswsock.h>
|
||||
#else
|
||||
#error UNKNOWN PLATFORM
|
||||
#endif
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_PORT_H
|
||||
311
Pods/gRPC-Core/include/grpc/event_engine/slice.h
generated
Normal file
311
Pods/gRPC-Core/include/grpc/event_engine/slice.h
generated
Normal file
@@ -0,0 +1,311 @@
|
||||
// Copyright 2022 gRPC authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef GRPC_EVENT_ENGINE_SLICE_H
|
||||
#define GRPC_EVENT_ENGINE_SLICE_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
#include <grpc/event_engine/internal/slice_cast.h>
|
||||
#include <grpc/slice.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
// This public slice definition largely based of the internal grpc_core::Slice
|
||||
// implementation. Changes to this implementation might warrant changes to the
|
||||
// internal grpc_core::Slice type as well.
|
||||
|
||||
namespace grpc_event_engine {
|
||||
namespace experimental {
|
||||
|
||||
// Forward declarations
|
||||
class Slice;
|
||||
class MutableSlice;
|
||||
|
||||
namespace slice_detail {
|
||||
|
||||
// Returns an empty slice.
|
||||
static constexpr grpc_slice EmptySlice() { return {nullptr, {}}; }
|
||||
|
||||
// BaseSlice holds the grpc_slice object, but does not apply refcounting policy.
|
||||
// It does export immutable access into the slice, such that this can be shared
|
||||
// by all storage policies.
|
||||
class BaseSlice {
|
||||
public:
|
||||
BaseSlice(const BaseSlice&) = delete;
|
||||
BaseSlice& operator=(const BaseSlice&) = delete;
|
||||
BaseSlice(BaseSlice&& other) = delete;
|
||||
BaseSlice& operator=(BaseSlice&& other) = delete;
|
||||
|
||||
// Iterator access to the underlying bytes
|
||||
const uint8_t* begin() const { return GRPC_SLICE_START_PTR(c_slice()); }
|
||||
const uint8_t* end() const { return GRPC_SLICE_END_PTR(c_slice()); }
|
||||
const uint8_t* cbegin() const { return GRPC_SLICE_START_PTR(c_slice()); }
|
||||
const uint8_t* cend() const { return GRPC_SLICE_END_PTR(c_slice()); }
|
||||
|
||||
// Retrieve a borrowed reference to the underlying grpc_slice.
|
||||
const grpc_slice& c_slice() const { return slice_; }
|
||||
|
||||
// Retrieve the underlying grpc_slice, and replace the one in this object with
|
||||
// EmptySlice().
|
||||
grpc_slice TakeCSlice() {
|
||||
grpc_slice out = slice_;
|
||||
slice_ = EmptySlice();
|
||||
return out;
|
||||
}
|
||||
|
||||
// As other things... borrowed references.
|
||||
absl::string_view as_string_view() const {
|
||||
return absl::string_view(reinterpret_cast<const char*>(data()), size());
|
||||
}
|
||||
|
||||
// Array access
|
||||
uint8_t operator[](size_t i) const {
|
||||
return GRPC_SLICE_START_PTR(c_slice())[i];
|
||||
}
|
||||
|
||||
// Access underlying data
|
||||
const uint8_t* data() const { return GRPC_SLICE_START_PTR(c_slice()); }
|
||||
|
||||
// Size of the slice
|
||||
size_t size() const { return GRPC_SLICE_LENGTH(c_slice()); }
|
||||
size_t length() const { return size(); }
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
// For inlined slices - are these two slices equal?
|
||||
// For non-inlined slices - do these two slices refer to the same block of
|
||||
// memory?
|
||||
bool is_equivalent(const BaseSlice& other) const {
|
||||
return grpc_slice_is_equivalent(slice_, other.slice_);
|
||||
}
|
||||
|
||||
uint32_t Hash() const;
|
||||
|
||||
protected:
|
||||
BaseSlice() : slice_(EmptySlice()) {}
|
||||
explicit BaseSlice(const grpc_slice& slice) : slice_(slice) {}
|
||||
~BaseSlice() = default;
|
||||
|
||||
void Swap(BaseSlice* other) { std::swap(slice_, other->slice_); }
|
||||
void SetCSlice(const grpc_slice& slice) { slice_ = slice; }
|
||||
|
||||
uint8_t* mutable_data() { return GRPC_SLICE_START_PTR(slice_); }
|
||||
|
||||
grpc_slice* c_slice_ptr() { return &slice_; }
|
||||
|
||||
private:
|
||||
grpc_slice slice_;
|
||||
};
|
||||
|
||||
inline bool operator==(const BaseSlice& a, const BaseSlice& b) {
|
||||
return grpc_slice_eq(a.c_slice(), b.c_slice()) != 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const BaseSlice& a, const BaseSlice& b) {
|
||||
return grpc_slice_eq(a.c_slice(), b.c_slice()) == 0;
|
||||
}
|
||||
|
||||
inline bool operator==(const BaseSlice& a, absl::string_view b) {
|
||||
return a.as_string_view() == b;
|
||||
}
|
||||
|
||||
inline bool operator!=(const BaseSlice& a, absl::string_view b) {
|
||||
return a.as_string_view() != b;
|
||||
}
|
||||
|
||||
inline bool operator==(absl::string_view a, const BaseSlice& b) {
|
||||
return a == b.as_string_view();
|
||||
}
|
||||
|
||||
inline bool operator!=(absl::string_view a, const BaseSlice& b) {
|
||||
return a != b.as_string_view();
|
||||
}
|
||||
|
||||
inline bool operator==(const BaseSlice& a, const grpc_slice& b) {
|
||||
return grpc_slice_eq(a.c_slice(), b) != 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const BaseSlice& a, const grpc_slice& b) {
|
||||
return grpc_slice_eq(a.c_slice(), b) == 0;
|
||||
}
|
||||
|
||||
inline bool operator==(const grpc_slice& a, const BaseSlice& b) {
|
||||
return grpc_slice_eq(a, b.c_slice()) != 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const grpc_slice& a, const BaseSlice& b) {
|
||||
return grpc_slice_eq(a, b.c_slice()) == 0;
|
||||
}
|
||||
|
||||
template <typename Out>
|
||||
struct CopyConstructors {
|
||||
static Out FromCopiedString(const char* s) {
|
||||
return FromCopiedBuffer(s, strlen(s));
|
||||
}
|
||||
static Out FromCopiedString(absl::string_view s) {
|
||||
return FromCopiedBuffer(s.data(), s.size());
|
||||
}
|
||||
static Out FromCopiedString(std::string s);
|
||||
|
||||
static Out FromCopiedBuffer(const char* p, size_t len) {
|
||||
return Out(grpc_slice_from_copied_buffer(p, len));
|
||||
}
|
||||
|
||||
static Out FromCopiedBuffer(const uint8_t* p, size_t len) {
|
||||
return Out(
|
||||
grpc_slice_from_copied_buffer(reinterpret_cast<const char*>(p), len));
|
||||
}
|
||||
|
||||
template <typename Buffer>
|
||||
static Out FromCopiedBuffer(const Buffer& buffer) {
|
||||
return FromCopiedBuffer(reinterpret_cast<const char*>(buffer.data()),
|
||||
buffer.size());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace slice_detail
|
||||
|
||||
class GPR_MSVC_EMPTY_BASE_CLASS_WORKAROUND MutableSlice
|
||||
: public slice_detail::BaseSlice,
|
||||
public slice_detail::CopyConstructors<MutableSlice> {
|
||||
public:
|
||||
MutableSlice() = default;
|
||||
explicit MutableSlice(const grpc_slice& slice);
|
||||
~MutableSlice();
|
||||
|
||||
MutableSlice(const MutableSlice&) = delete;
|
||||
MutableSlice& operator=(const MutableSlice&) = delete;
|
||||
MutableSlice(MutableSlice&& other) noexcept
|
||||
: slice_detail::BaseSlice(other.TakeCSlice()) {}
|
||||
MutableSlice& operator=(MutableSlice&& other) noexcept {
|
||||
Swap(&other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static MutableSlice CreateUninitialized(size_t length) {
|
||||
return MutableSlice(grpc_slice_malloc(length));
|
||||
}
|
||||
|
||||
// Return a sub slice of this one. Leaves this slice in an indeterminate but
|
||||
// valid state.
|
||||
MutableSlice TakeSubSlice(size_t pos, size_t n) {
|
||||
return MutableSlice(grpc_slice_sub_no_ref(TakeCSlice(), pos, pos + n));
|
||||
}
|
||||
|
||||
// Iterator access to the underlying bytes
|
||||
uint8_t* begin() { return mutable_data(); }
|
||||
uint8_t* end() { return mutable_data() + size(); }
|
||||
uint8_t* data() { return mutable_data(); }
|
||||
|
||||
// Array access
|
||||
uint8_t& operator[](size_t i) { return mutable_data()[i]; }
|
||||
};
|
||||
|
||||
class GPR_MSVC_EMPTY_BASE_CLASS_WORKAROUND Slice
|
||||
: public slice_detail::BaseSlice,
|
||||
public slice_detail::CopyConstructors<Slice> {
|
||||
public:
|
||||
Slice() = default;
|
||||
~Slice();
|
||||
explicit Slice(const grpc_slice& slice) : slice_detail::BaseSlice(slice) {}
|
||||
explicit Slice(slice_detail::BaseSlice&& other)
|
||||
: slice_detail::BaseSlice(other.TakeCSlice()) {}
|
||||
|
||||
Slice(const Slice&) = delete;
|
||||
Slice& operator=(const Slice&) = delete;
|
||||
Slice(Slice&& other) noexcept : slice_detail::BaseSlice(other.TakeCSlice()) {}
|
||||
Slice& operator=(Slice&& other) noexcept {
|
||||
Swap(&other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// A slice might refer to some memory that we keep a refcount to (this is
|
||||
// owned), or some memory that's inlined into the slice (also owned), or some
|
||||
// other block of memory that we know will be available for the lifetime of
|
||||
// some operation in the common case (not owned). In the *less common* case
|
||||
// that we need to keep that slice text for longer than our API's guarantee us
|
||||
// access, we need to take a copy and turn this into something that we do own.
|
||||
|
||||
// TakeOwned returns an owned slice regardless of current ownership, and
|
||||
// leaves the current slice in a valid but externally unpredictable state - in
|
||||
// doing so it can avoid adding a ref to the underlying slice.
|
||||
Slice TakeOwned();
|
||||
|
||||
// AsOwned returns an owned slice but does not mutate the current slice,
|
||||
// meaning that it may add a reference to the underlying slice.
|
||||
Slice AsOwned() const;
|
||||
|
||||
// TakeMutable returns a MutableSlice, and leaves the current slice in an
|
||||
// indeterminate but valid state.
|
||||
// A mutable slice requires only one reference to the bytes of the slice -
|
||||
// this can be achieved either with inlined storage or with a single
|
||||
// reference.
|
||||
// If the current slice is refcounted and there are more than one references
|
||||
// to that slice, then the slice is copied in order to achieve a mutable
|
||||
// version.
|
||||
MutableSlice TakeMutable();
|
||||
|
||||
// Return a sub slice of this one. Leaves this slice in an indeterminate but
|
||||
// valid state.
|
||||
Slice TakeSubSlice(size_t pos, size_t n) {
|
||||
return Slice(grpc_slice_sub_no_ref(TakeCSlice(), pos, pos + n));
|
||||
}
|
||||
|
||||
// Return a sub slice of this one. Adds a reference to the underlying slice.
|
||||
Slice RefSubSlice(size_t pos, size_t n) const {
|
||||
return Slice(grpc_slice_sub(c_slice(), pos, pos + n));
|
||||
}
|
||||
|
||||
// Split this slice, returning a new slice containing (split:end] and
|
||||
// leaving this slice with [begin:split).
|
||||
Slice Split(size_t split) {
|
||||
return Slice(grpc_slice_split_tail(c_slice_ptr(), split));
|
||||
}
|
||||
|
||||
Slice Ref() const;
|
||||
|
||||
Slice Copy() const { return Slice(grpc_slice_copy(c_slice())); }
|
||||
|
||||
static Slice FromRefcountAndBytes(grpc_slice_refcount* r,
|
||||
const uint8_t* begin, const uint8_t* end);
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
template <>
|
||||
struct SliceCastable<Slice, grpc_slice> {};
|
||||
template <>
|
||||
struct SliceCastable<grpc_slice, Slice> {};
|
||||
|
||||
template <>
|
||||
struct SliceCastable<MutableSlice, grpc_slice> {};
|
||||
template <>
|
||||
struct SliceCastable<grpc_slice, MutableSlice> {};
|
||||
|
||||
template <>
|
||||
struct SliceCastable<MutableSlice, Slice> {};
|
||||
template <>
|
||||
struct SliceCastable<Slice, MutableSlice> {};
|
||||
} // namespace internal
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_SLICE_H
|
||||
159
Pods/gRPC-Core/include/grpc/event_engine/slice_buffer.h
generated
Normal file
159
Pods/gRPC-Core/include/grpc/event_engine/slice_buffer.h
generated
Normal file
@@ -0,0 +1,159 @@
|
||||
// Copyright 2022 gRPC authors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef GRPC_EVENT_ENGINE_SLICE_BUFFER_H
|
||||
#define GRPC_EVENT_ENGINE_SLICE_BUFFER_H
|
||||
|
||||
#include <grpc/support/port_platform.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/utility/utility.h"
|
||||
|
||||
#include <grpc/event_engine/internal/slice_cast.h>
|
||||
#include <grpc/event_engine/slice.h>
|
||||
#include <grpc/impl/codegen/slice.h>
|
||||
#include <grpc/slice.h>
|
||||
#include <grpc/slice_buffer.h>
|
||||
#include <grpc/support/log.h>
|
||||
|
||||
namespace grpc_event_engine {
|
||||
namespace experimental {
|
||||
|
||||
/// A Wrapper around \a grpc_slice_buffer pointer.
|
||||
///
|
||||
/// A slice buffer holds the memory for a collection of slices.
|
||||
/// The SliceBuffer object itself is meant to only hide the C-style API,
|
||||
/// and won't hold the data itself. In terms of lifespan, the
|
||||
/// grpc_slice_buffer ought to be kept somewhere inside the caller's objects,
|
||||
/// like a transport or an endpoint.
|
||||
///
|
||||
/// This lifespan rule is likely to change in the future, as we may
|
||||
/// collapse the grpc_slice_buffer structure straight into this class.
|
||||
///
|
||||
/// The SliceBuffer API is basically a replica of the grpc_slice_buffer's,
|
||||
/// and its documentation will move here once we remove the C structure,
|
||||
/// which should happen before the EventEngine's API is no longer
|
||||
/// an experimental API.
|
||||
class SliceBuffer {
|
||||
public:
|
||||
SliceBuffer() { grpc_slice_buffer_init(&slice_buffer_); }
|
||||
SliceBuffer(const SliceBuffer& other) = delete;
|
||||
SliceBuffer(SliceBuffer&& other) noexcept
|
||||
: slice_buffer_(other.slice_buffer_) {
|
||||
grpc_slice_buffer_init(&slice_buffer_);
|
||||
grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_);
|
||||
}
|
||||
/// Upon destruction, the underlying raw slice buffer is cleaned out and all
|
||||
/// slices are unreffed.
|
||||
~SliceBuffer() { grpc_slice_buffer_destroy(&slice_buffer_); }
|
||||
|
||||
SliceBuffer& operator=(const SliceBuffer&) = delete;
|
||||
SliceBuffer& operator=(SliceBuffer&& other) noexcept {
|
||||
grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Swap the contents of this SliceBuffer with the contents of another.
|
||||
void Swap(SliceBuffer& other) {
|
||||
grpc_slice_buffer_swap(&slice_buffer_, &other.slice_buffer_);
|
||||
}
|
||||
|
||||
/// Appends a new slice into the SliceBuffer and makes an attempt to merge
|
||||
/// this slice with the last slice in the SliceBuffer.
|
||||
void Append(Slice slice);
|
||||
|
||||
/// Adds a new slice into the SliceBuffer at the next available index.
|
||||
/// Returns the index at which the new slice is added.
|
||||
size_t AppendIndexed(Slice slice);
|
||||
|
||||
/// Returns the number of slices held by the SliceBuffer.
|
||||
size_t Count() { return slice_buffer_.count; }
|
||||
|
||||
/// Removes/deletes the last n bytes in the SliceBuffer.
|
||||
void RemoveLastNBytes(size_t n) {
|
||||
grpc_slice_buffer_trim_end(&slice_buffer_, n, nullptr);
|
||||
}
|
||||
|
||||
/// Move the first n bytes of the SliceBuffer into a memory pointed to by dst.
|
||||
void MoveFirstNBytesIntoBuffer(size_t n, void* dst) {
|
||||
grpc_slice_buffer_move_first_into_buffer(&slice_buffer_, n, dst);
|
||||
}
|
||||
|
||||
/// Removes/deletes the last n bytes in the SliceBuffer and add it to the
|
||||
/// other SliceBuffer
|
||||
void MoveLastNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) {
|
||||
grpc_slice_buffer_trim_end(&slice_buffer_, n, &other.slice_buffer_);
|
||||
}
|
||||
|
||||
/// Move the first n bytes of the SliceBuffer into the other SliceBuffer
|
||||
void MoveFirstNBytesIntoSliceBuffer(size_t n, SliceBuffer& other) {
|
||||
grpc_slice_buffer_move_first(&slice_buffer_, n, &other.slice_buffer_);
|
||||
}
|
||||
|
||||
/// Removes and unrefs all slices in the SliceBuffer.
|
||||
void Clear() { grpc_slice_buffer_reset_and_unref(&slice_buffer_); }
|
||||
|
||||
/// Removes the first slice in the SliceBuffer and returns it.
|
||||
Slice TakeFirst();
|
||||
|
||||
/// Prepends the slice to the the front of the SliceBuffer.
|
||||
void Prepend(Slice slice);
|
||||
|
||||
/// Increased the ref-count of slice at the specified index and returns the
|
||||
/// associated slice.
|
||||
Slice RefSlice(size_t index);
|
||||
|
||||
/// Array access into the SliceBuffer. It returns a non mutable reference to
|
||||
/// the slice at the specified index
|
||||
const Slice& operator[](size_t index) const {
|
||||
return internal::SliceCast<Slice>(slice_buffer_.slices[index]);
|
||||
}
|
||||
|
||||
/// Return mutable reference to the slice at the specified index
|
||||
Slice& MutableSliceAt(size_t index) const {
|
||||
return internal::SliceCast<Slice>(slice_buffer_.slices[index]);
|
||||
}
|
||||
|
||||
/// The total number of bytes held by the SliceBuffer
|
||||
size_t Length() const { return slice_buffer_.length; }
|
||||
|
||||
/// Return a pointer to the back raw grpc_slice_buffer
|
||||
grpc_slice_buffer* c_slice_buffer() { return &slice_buffer_; }
|
||||
|
||||
// Returns a SliceBuffer that transfers slices into this new SliceBuffer,
|
||||
// leaving the input parameter empty.
|
||||
static SliceBuffer TakeCSliceBuffer(grpc_slice_buffer& slice_buffer) {
|
||||
return SliceBuffer(&slice_buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
// Transfers slices into this new SliceBuffer, leaving the parameter empty.
|
||||
// Does not take ownership of the slice_buffer argument.
|
||||
explicit SliceBuffer(grpc_slice_buffer* slice_buffer) {
|
||||
grpc_slice_buffer_init(&slice_buffer_);
|
||||
grpc_slice_buffer_swap(&slice_buffer_, slice_buffer);
|
||||
}
|
||||
/// The backing raw slice buffer.
|
||||
grpc_slice_buffer slice_buffer_;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace grpc_event_engine
|
||||
|
||||
#endif // GRPC_EVENT_ENGINE_SLICE_BUFFER_H
|
||||
Reference in New Issue
Block a user