A starter slice buffer implementation to unblock event engine endpoints (#29367)

* A starter SliceBuffer implementation

* Add comments and fix sanity checks

* Minor fixes

* more minor fixes

* Addressing review comments and adding a slice_buffer_test

* fix sanity checks

* regenerate projects

* fixing undefined function error

* reverting changes from memory_allocator.cc and adding them to src/core/lib/slice/slice_buffer.cc to allow memory allocator lib to build correctly

* fix sanity checks

* adding an open source slice definition

* regnerate projects

* fix asan error

* Automated change: Fix sanity tests

* addressing review comments

* fix sanity checks

* regenerate projects

* update

* fix sanity checks

* Converting slice buffer to retarin ownership of the underlying ctype

* fix nits

Co-authored-by: Vignesh2208 <Vignesh2208@users.noreply.github.com>
pull/29647/head
Vignesh Babu 3 years ago committed by GitHub
parent 4ab3103293
commit 1494b1ef26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      BUILD
  2. 100
      CMakeLists.txt
  3. 8
      Makefile
  4. 35
      build_autogenerated.yaml
  5. 2
      config.m4
  6. 2
      config.w32
  7. 4
      gRPC-Core.podspec
  8. 4
      grpc.gemspec
  9. 4
      grpc.gyp
  10. 1
      include/grpc/event_engine/event_engine.h
  11. 15
      include/grpc/event_engine/memory_allocator.h
  12. 286
      include/grpc/event_engine/slice.h
  13. 112
      include/grpc/event_engine/slice_buffer.h
  14. 2
      include/grpc/impl/codegen/slice.h
  15. 4
      package.xml
  16. 102
      src/core/lib/event_engine/slice.cc
  17. 49
      src/core/lib/event_engine/slice_buffer.cc
  18. 5
      src/core/lib/slice/slice.h
  19. 2
      src/python/grpcio/grpc_core_dependencies.py
  20. 10
      test/core/event_engine/BUILD
  21. 79
      test/core/event_engine/slice_buffer_test.cc
  22. 2
      tools/doxygen/Doxyfile.c++
  23. 4
      tools/doxygen/Doxyfile.c++.internal
  24. 2
      tools/doxygen/Doxyfile.core
  25. 4
      tools/doxygen/Doxyfile.core.internal
  26. 72
      tools/run_tests/generated/tests.json

@ -201,6 +201,8 @@ GRPC_PUBLIC_EVENT_ENGINE_HDRS = [
"include/grpc/event_engine/memory_allocator.h",
"include/grpc/event_engine/memory_request.h",
"include/grpc/event_engine/internal/memory_allocator_impl.h",
"include/grpc/event_engine/slice.h",
"include/grpc/event_engine/slice_buffer.h",
]
GRPCXX_SRCS = [
@ -1840,10 +1842,16 @@ grpc_cc_library(
name = "event_engine_common",
srcs = [
"src/core/lib/event_engine/resolved_address.cc",
"src/core/lib/event_engine/slice.cc",
"src/core/lib/event_engine/slice_buffer.cc",
],
deps = [
"event_engine_base_hdrs",
"gpr_base",
"gpr_platform",
"ref_counted",
"slice",
"slice_refcount",
],
)

100
CMakeLists.txt generated

@ -864,7 +864,6 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_c server_ssl_test)
endif()
add_dependencies(buildtests_c server_test)
add_dependencies(buildtests_c slice_buffer_test)
add_dependencies(buildtests_c slice_split_test)
add_dependencies(buildtests_c slice_string_helpers_test)
add_dependencies(buildtests_c sockaddr_resolver_test)
@ -890,6 +889,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_c tcp_server_posix_test)
endif()
add_dependencies(buildtests_c test_core_gpr_time_test)
add_dependencies(buildtests_c test_core_slice_slice_buffer_test)
add_dependencies(buildtests_c thd_test)
add_dependencies(buildtests_c threadpool_test)
add_dependencies(buildtests_c time_averaged_stats_test)
@ -1137,6 +1137,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx streams_not_seen_test)
add_dependencies(buildtests_cxx string_ref_test)
add_dependencies(buildtests_cxx table_test)
add_dependencies(buildtests_cxx test_core_event_engine_slice_buffer_test)
add_dependencies(buildtests_cxx test_core_gprpp_time_test)
add_dependencies(buildtests_cxx test_core_security_credentials_test)
add_dependencies(buildtests_cxx test_core_slice_slice_test)
@ -2027,6 +2028,8 @@ add_library(grpc
src/core/lib/event_engine/event_engine.cc
src/core/lib/event_engine/memory_allocator.cc
src/core/lib/event_engine/resolved_address.cc
src/core/lib/event_engine/slice.cc
src/core/lib/event_engine/slice_buffer.cc
src/core/lib/event_engine/sockaddr.cc
src/core/lib/gprpp/time.cc
src/core/lib/http/format_request.cc
@ -2332,6 +2335,8 @@ foreach(_hdr
include/grpc/event_engine/memory_allocator.h
include/grpc/event_engine/memory_request.h
include/grpc/event_engine/port.h
include/grpc/event_engine/slice.h
include/grpc/event_engine/slice_buffer.h
include/grpc/fork.h
include/grpc/grpc.h
include/grpc/grpc_posix.h
@ -2636,6 +2641,8 @@ add_library(grpc_unsecure
src/core/lib/event_engine/event_engine.cc
src/core/lib/event_engine/memory_allocator.cc
src/core/lib/event_engine/resolved_address.cc
src/core/lib/event_engine/slice.cc
src/core/lib/event_engine/slice_buffer.cc
src/core/lib/event_engine/sockaddr.cc
src/core/lib/gprpp/time.cc
src/core/lib/http/format_request.cc
@ -2876,6 +2883,8 @@ foreach(_hdr
include/grpc/event_engine/memory_allocator.h
include/grpc/event_engine/memory_request.h
include/grpc/event_engine/port.h
include/grpc/event_engine/slice.h
include/grpc/event_engine/slice_buffer.h
include/grpc/fork.h
include/grpc/grpc.h
include/grpc/grpc_posix.h
@ -6570,33 +6579,6 @@ target_link_libraries(server_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(slice_buffer_test
test/core/slice/slice_buffer_test.cc
)
target_include_directories(slice_buffer_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
)
target_link_libraries(slice_buffer_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)
@ -7018,6 +7000,33 @@ target_link_libraries(test_core_gpr_time_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(test_core_slice_slice_buffer_test
test/core/slice/slice_buffer_test.cc
)
target_include_directories(test_core_slice_slice_buffer_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
)
target_link_libraries(test_core_slice_slice_buffer_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)
@ -15826,6 +15835,41 @@ target_link_libraries(table_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(test_core_event_engine_slice_buffer_test
test/core/event_engine/slice_buffer_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(test_core_event_engine_slice_buffer_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(test_core_event_engine_slice_buffer_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)

8
Makefile generated

@ -1446,6 +1446,8 @@ LIBGRPC_SRC = \
src/core/lib/event_engine/event_engine.cc \
src/core/lib/event_engine/memory_allocator.cc \
src/core/lib/event_engine/resolved_address.cc \
src/core/lib/event_engine/slice.cc \
src/core/lib/event_engine/slice_buffer.cc \
src/core/lib/event_engine/sockaddr.cc \
src/core/lib/gprpp/time.cc \
src/core/lib/http/format_request.cc \
@ -1696,6 +1698,8 @@ PUBLIC_HEADERS_C += \
include/grpc/event_engine/memory_allocator.h \
include/grpc/event_engine/memory_request.h \
include/grpc/event_engine/port.h \
include/grpc/event_engine/slice.h \
include/grpc/event_engine/slice_buffer.h \
include/grpc/fork.h \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \
@ -1898,6 +1902,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/event_engine/event_engine.cc \
src/core/lib/event_engine/memory_allocator.cc \
src/core/lib/event_engine/resolved_address.cc \
src/core/lib/event_engine/slice.cc \
src/core/lib/event_engine/slice_buffer.cc \
src/core/lib/event_engine/sockaddr.cc \
src/core/lib/gprpp/time.cc \
src/core/lib/http/format_request.cc \
@ -2084,6 +2090,8 @@ PUBLIC_HEADERS_C += \
include/grpc/event_engine/memory_allocator.h \
include/grpc/event_engine/memory_request.h \
include/grpc/event_engine/port.h \
include/grpc/event_engine/slice.h \
include/grpc/event_engine/slice_buffer.h \
include/grpc/fork.h \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \

@ -302,6 +302,8 @@ libs:
- include/grpc/event_engine/memory_allocator.h
- include/grpc/event_engine/memory_request.h
- include/grpc/event_engine/port.h
- include/grpc/event_engine/slice.h
- include/grpc/event_engine/slice_buffer.h
- include/grpc/fork.h
- include/grpc/grpc.h
- include/grpc/grpc_posix.h
@ -1403,6 +1405,8 @@ libs:
- src/core/lib/event_engine/event_engine.cc
- src/core/lib/event_engine/memory_allocator.cc
- src/core/lib/event_engine/resolved_address.cc
- src/core/lib/event_engine/slice.cc
- src/core/lib/event_engine/slice_buffer.cc
- src/core/lib/event_engine/sockaddr.cc
- src/core/lib/gprpp/time.cc
- src/core/lib/http/format_request.cc
@ -1778,6 +1782,8 @@ libs:
- include/grpc/event_engine/memory_allocator.h
- include/grpc/event_engine/memory_request.h
- include/grpc/event_engine/port.h
- include/grpc/event_engine/slice.h
- include/grpc/event_engine/slice_buffer.h
- include/grpc/fork.h
- include/grpc/grpc.h
- include/grpc/grpc_posix.h
@ -2241,6 +2247,8 @@ libs:
- src/core/lib/event_engine/event_engine.cc
- src/core/lib/event_engine/memory_allocator.cc
- src/core/lib/event_engine/resolved_address.cc
- src/core/lib/event_engine/slice.cc
- src/core/lib/event_engine/slice_buffer.cc
- src/core/lib/event_engine/sockaddr.cc
- src/core/lib/gprpp/time.cc
- src/core/lib/http/format_request.cc
@ -4045,15 +4053,6 @@ targets:
- test/core/surface/server_test.cc
deps:
- grpc_test_util
- name: slice_buffer_test
build: test
language: c
headers: []
src:
- test/core/slice/slice_buffer_test.cc
deps:
- grpc_test_util
uses_polling: false
- name: slice_split_test
build: test
language: c
@ -4217,6 +4216,15 @@ targets:
deps:
- grpc_test_util
uses_polling: false
- name: test_core_slice_slice_buffer_test
build: test
language: c
headers: []
src:
- test/core/slice/slice_buffer_test.cc
deps:
- grpc_test_util
uses_polling: false
- name: thd_test
build: test
language: c
@ -7706,6 +7714,15 @@ targets:
- absl/types:optional
- absl/utility:utility
uses_polling: false
- name: test_core_event_engine_slice_buffer_test
gtest: true
build: test
language: c++
headers: []
src:
- test/core/event_engine/slice_buffer_test.cc
deps:
- grpc_test_util
- name: test_core_gprpp_time_test
gtest: true
build: test

2
config.m4 generated

@ -468,6 +468,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/event_engine/event_engine.cc \
src/core/lib/event_engine/memory_allocator.cc \
src/core/lib/event_engine/resolved_address.cc \
src/core/lib/event_engine/slice.cc \
src/core/lib/event_engine/slice_buffer.cc \
src/core/lib/event_engine/sockaddr.cc \
src/core/lib/gpr/alloc.cc \
src/core/lib/gpr/atm.cc \

2
config.w32 generated

@ -434,6 +434,8 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\event_engine\\event_engine.cc " +
"src\\core\\lib\\event_engine\\memory_allocator.cc " +
"src\\core\\lib\\event_engine\\resolved_address.cc " +
"src\\core\\lib\\event_engine\\slice.cc " +
"src\\core\\lib\\event_engine\\slice_buffer.cc " +
"src\\core\\lib\\event_engine\\sockaddr.cc " +
"src\\core\\lib\\gpr\\alloc.cc " +
"src\\core\\lib\\gpr\\atm.cc " +

4
gRPC-Core.podspec generated

@ -113,6 +113,8 @@ Pod::Spec.new do |s|
'include/grpc/event_engine/memory_allocator.h',
'include/grpc/event_engine/memory_request.h',
'include/grpc/event_engine/port.h',
'include/grpc/event_engine/slice.h',
'include/grpc/event_engine/slice_buffer.h',
'include/grpc/fork.h',
'include/grpc/grpc.h',
'include/grpc/grpc_posix.h',
@ -1036,6 +1038,8 @@ Pod::Spec.new do |s|
'src/core/lib/event_engine/event_engine_factory.h',
'src/core/lib/event_engine/memory_allocator.cc',
'src/core/lib/event_engine/resolved_address.cc',
'src/core/lib/event_engine/slice.cc',
'src/core/lib/event_engine/slice_buffer.cc',
'src/core/lib/event_engine/sockaddr.cc',
'src/core/lib/event_engine/sockaddr.h',
'src/core/lib/gpr/alloc.cc',

4
grpc.gemspec generated

@ -57,6 +57,8 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/event_engine/memory_allocator.h )
s.files += %w( include/grpc/event_engine/memory_request.h )
s.files += %w( include/grpc/event_engine/port.h )
s.files += %w( include/grpc/event_engine/slice.h )
s.files += %w( include/grpc/event_engine/slice_buffer.h )
s.files += %w( include/grpc/fork.h )
s.files += %w( include/grpc/grpc.h )
s.files += %w( include/grpc/grpc_posix.h )
@ -951,6 +953,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/event_engine/event_engine_factory.h )
s.files += %w( src/core/lib/event_engine/memory_allocator.cc )
s.files += %w( src/core/lib/event_engine/resolved_address.cc )
s.files += %w( src/core/lib/event_engine/slice.cc )
s.files += %w( src/core/lib/event_engine/slice_buffer.cc )
s.files += %w( src/core/lib/event_engine/sockaddr.cc )
s.files += %w( src/core/lib/event_engine/sockaddr.h )
s.files += %w( src/core/lib/gpr/alloc.cc )

4
grpc.gyp generated

@ -801,6 +801,8 @@
'src/core/lib/event_engine/event_engine.cc',
'src/core/lib/event_engine/memory_allocator.cc',
'src/core/lib/event_engine/resolved_address.cc',
'src/core/lib/event_engine/slice.cc',
'src/core/lib/event_engine/slice_buffer.cc',
'src/core/lib/event_engine/sockaddr.cc',
'src/core/lib/gprpp/time.cc',
'src/core/lib/http/format_request.cc',
@ -1262,6 +1264,8 @@
'src/core/lib/event_engine/event_engine.cc',
'src/core/lib/event_engine/memory_allocator.cc',
'src/core/lib/event_engine/resolved_address.cc',
'src/core/lib/event_engine/slice.cc',
'src/core/lib/event_engine/slice_buffer.cc',
'src/core/lib/event_engine/sockaddr.cc',
'src/core/lib/gprpp/time.cc',
'src/core/lib/http/format_request.cc',

@ -26,6 +26,7 @@
#include <grpc/event_engine/endpoint_config.h>
#include <grpc/event_engine/memory_allocator.h>
#include <grpc/event_engine/port.h>
#include <grpc/event_engine/slice_buffer.h>
// TODO(hork): Define the Endpoint::Write metrics collection system
namespace grpc_event_engine {

@ -26,24 +26,9 @@
#include <grpc/event_engine/internal/memory_allocator_impl.h>
#include <grpc/slice.h>
// forward-declaring an internal struct, not used publicly.
struct grpc_slice_buffer;
namespace grpc_event_engine {
namespace experimental {
// TODO(nnoble): needs implementation
class SliceBuffer {
public:
SliceBuffer() { abort(); }
explicit SliceBuffer(grpc_slice_buffer*) { abort(); }
grpc_slice_buffer* RawSliceBuffer() { return slice_buffer_; }
private:
grpc_slice_buffer* slice_buffer_;
};
// Tracks memory allocated by one system.
// Is effectively a thin wrapper/smart pointer for a MemoryAllocatorImpl,
// providing a convenient and stable API.

@ -0,0 +1,286 @@
// 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/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));
}
template <typename Buffer>
static Out FromCopiedBuffer(const Buffer& buffer) {
return FromCopiedBuffer(reinterpret_cast<const char*>(buffer.data()),
buffer.size());
}
};
} // namespace slice_detail
class 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 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 experimental
} // namespace grpc_event_engine
#endif // GRPC_EVENT_ENGINE_SLICE_H

@ -0,0 +1,112 @@
// 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/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 Event Engine's API is no longer
/// an experimental API.
class SliceBuffer {
public:
explicit SliceBuffer() { grpc_slice_buffer_init(&slice_buffer_); }
SliceBuffer(const SliceBuffer& other) = delete;
SliceBuffer(SliceBuffer&& other) noexcept
: slice_buffer_(other.slice_buffer_) {
grpc_slice_buffer_reset_and_unref(&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_); }
/// 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 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);
/// The total number of bytes held by the SliceBuffer
size_t Length() { return slice_buffer_.length; }
/// Return a pointer to the back raw grpc_slice_buffer
grpc_slice_buffer* RawSliceBuffer() { return &slice_buffer_; }
private:
/// The backing raw slice buffer.
grpc_slice_buffer slice_buffer_;
};
} // namespace experimental
} // namespace grpc_event_engine
#endif // GRPC_EVENT_ENGINE_SLICE_BUFFER_H

@ -19,7 +19,7 @@
#ifndef GRPC_IMPL_CODEGEN_SLICE_H
#define GRPC_IMPL_CODEGEN_SLICE_H
// IWYU pragma: private, include <grpc/slice.h>
// IWYU pragma: private
#include <grpc/impl/codegen/port_platform.h>

4
package.xml generated

@ -39,6 +39,8 @@
<file baseinstalldir="/" name="include/grpc/event_engine/memory_allocator.h" role="src" />
<file baseinstalldir="/" name="include/grpc/event_engine/memory_request.h" role="src" />
<file baseinstalldir="/" name="include/grpc/event_engine/port.h" role="src" />
<file baseinstalldir="/" name="include/grpc/event_engine/slice.h" role="src" />
<file baseinstalldir="/" name="include/grpc/event_engine/slice_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/fork.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc_posix.h" role="src" />
@ -933,6 +935,8 @@
<file baseinstalldir="/" name="src/core/lib/event_engine/event_engine_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/memory_allocator.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/resolved_address.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/slice.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/slice_buffer.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/sockaddr.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/sockaddr.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/alloc.cc" role="src" />

@ -0,0 +1,102 @@
// 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.
#include <grpc/support/port_platform.h>
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <grpc/event_engine/slice.h>
#include <grpc/slice.h>
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_refcount.h"
#include "src/core/lib/slice/slice_refcount_base.h"
namespace grpc_event_engine {
namespace experimental {
namespace slice_detail {
uint32_t BaseSlice::Hash() const { return grpc_slice_hash_internal(slice_); }
template <>
MutableSlice CopyConstructors<MutableSlice>::FromCopiedString(std::string s) {
return MutableSlice(grpc_slice_from_cpp_string(std::move(s)));
}
template <>
Slice CopyConstructors<Slice>::FromCopiedString(std::string s) {
return Slice(grpc_slice_from_cpp_string(std::move(s)));
}
} // namespace slice_detail
MutableSlice::MutableSlice(const grpc_slice& slice)
: slice_detail::BaseSlice(slice) {
GPR_DEBUG_ASSERT(slice.refcount == nullptr || slice.refcount->IsUnique());
}
MutableSlice::~MutableSlice() { grpc_slice_unref_internal(c_slice()); }
Slice Slice::TakeOwned() {
if (c_slice().refcount == nullptr) {
return Slice(c_slice());
}
if (c_slice().refcount == grpc_slice_refcount::NoopRefcount()) {
return Slice(grpc_slice_copy(c_slice()));
}
return Slice(TakeCSlice());
}
Slice Slice::AsOwned() const {
if (c_slice().refcount == nullptr) {
return Slice(c_slice());
}
if (c_slice().refcount == grpc_slice_refcount::NoopRefcount()) {
return Slice(grpc_slice_copy(c_slice()));
}
return Slice(grpc_slice_ref_internal(c_slice()));
}
MutableSlice Slice::TakeMutable() {
if (c_slice().refcount == nullptr) {
return MutableSlice(c_slice());
}
if (c_slice().refcount != grpc_slice_refcount::NoopRefcount() &&
c_slice().refcount->IsUnique()) {
return MutableSlice(TakeCSlice());
}
return MutableSlice(grpc_slice_copy(c_slice()));
}
Slice::~Slice() { grpc_slice_unref_internal(c_slice()); }
Slice Slice::Ref() const { return Slice(grpc_slice_ref_internal(c_slice())); }
Slice Slice::FromRefcountAndBytes(grpc_slice_refcount* r, const uint8_t* begin,
const uint8_t* end) {
grpc_slice out;
out.refcount = r;
if (r != grpc_slice_refcount::NoopRefcount()) r->Ref();
out.data.refcounted.bytes = const_cast<uint8_t*>(begin);
out.data.refcounted.length = end - begin;
return Slice(out);
}
} // namespace experimental
} // namespace grpc_event_engine

@ -0,0 +1,49 @@
// 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.
#include <grpc/support/port_platform.h>
#include <grpc/event_engine/slice_buffer.h>
#include <grpc/slice.h>
#include <grpc/slice_buffer.h>
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_refcount.h"
namespace grpc_event_engine {
namespace experimental {
void SliceBuffer::Append(Slice slice) {
grpc_slice_buffer_add(&slice_buffer_, slice.TakeCSlice());
}
size_t SliceBuffer::AppendIndexed(Slice slice) {
return grpc_slice_buffer_add_indexed(&slice_buffer_, slice.TakeCSlice());
}
Slice SliceBuffer::TakeFirst() {
return Slice(grpc_slice_buffer_take_first(&slice_buffer_));
}
void SliceBuffer::Prepend(Slice slice) {
grpc_slice_buffer_undo_take_first(&slice_buffer_, slice.TakeCSlice());
}
Slice SliceBuffer::RefSlice(size_t index) {
return Slice(grpc_slice_ref_internal(slice_buffer_.slices[index]));
}
} // namespace experimental
} // namespace grpc_event_engine

@ -46,6 +46,11 @@
// MutableSlice - provides a guarantee of unique ownership, meaning the
// underlying data can be mutated safely.
// This slice implementation is an extension of the event engine Slice
// implementation defined in <grpc/event_engine/slice.h>. Changes to this
// implementation might warrant changes to the public event engine Slice
// type as well.
namespace grpc_core {
namespace slice_detail {

@ -443,6 +443,8 @@ CORE_SOURCE_FILES = [
'src/core/lib/event_engine/event_engine.cc',
'src/core/lib/event_engine/memory_allocator.cc',
'src/core/lib/event_engine/resolved_address.cc',
'src/core/lib/event_engine/slice.cc',
'src/core/lib/event_engine/slice_buffer.cc',
'src/core/lib/event_engine/sockaddr.cc',
'src/core/lib/gpr/alloc.cc',
'src/core/lib/gpr/atm.cc',

@ -43,6 +43,16 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "slice_buffer_test",
srcs = ["slice_buffer_test.cc"],
external_deps = ["gtest"],
deps = [
"//:grpc",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_library(
name = "test_init",
srcs = ["test_init.cc"],

@ -0,0 +1,79 @@
// Copyright 2022 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.
#include <grpc/support/port_platform.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <grpc/event_engine/slice_buffer.h>
#include <grpc/grpc.h>
#include "src/core/lib/slice/slice.h"
#include "test/core/util/test_config.h"
using ::grpc_event_engine::experimental::Slice;
using ::grpc_event_engine::experimental::SliceBuffer;
static constexpr int kNewSliceLength = 100;
Slice MakeSlice(size_t len) {
GPR_ASSERT(len > 0);
unsigned char* contents = reinterpret_cast<unsigned char*>(new char[len]);
memset(contents, 'a', len);
return Slice(grpc_slice_new(contents, len, gpr_free));
}
TEST(SliceBufferTest, AddAndRemoveTest) {
SliceBuffer sb;
Slice first_slice = MakeSlice(kNewSliceLength);
Slice second_slice = MakeSlice(kNewSliceLength);
Slice first_slice_copy = first_slice.Copy();
sb.Append(std::move(first_slice));
sb.Append(std::move(second_slice));
ASSERT_EQ(sb.Count(), 2);
ASSERT_EQ(sb.Length(), 2 * kNewSliceLength);
Slice popped = sb.TakeFirst();
ASSERT_EQ(popped, first_slice_copy);
ASSERT_EQ(sb.Count(), 1);
ASSERT_EQ(sb.Length(), kNewSliceLength);
sb.Prepend(std::move(popped));
ASSERT_EQ(sb.Count(), 2);
ASSERT_EQ(sb.Length(), 2 * kNewSliceLength);
sb.Clear();
ASSERT_EQ(sb.Count(), 0);
ASSERT_EQ(sb.Length(), 0);
}
TEST(SliceBufferTest, SliceRefTest) {
SliceBuffer sb;
Slice first_slice = MakeSlice(kNewSliceLength);
Slice second_slice = MakeSlice(kNewSliceLength + 1);
Slice first_slice_copy = first_slice.Copy();
Slice second_slice_copy = second_slice.Copy();
ASSERT_EQ(sb.AppendIndexed(std::move(first_slice)), 0);
ASSERT_EQ(sb.AppendIndexed(std::move(second_slice)), 1);
Slice first_reffed = sb.RefSlice(0);
Slice second_reffed = sb.RefSlice(1);
ASSERT_EQ(first_reffed, first_slice_copy);
ASSERT_EQ(second_reffed, second_slice_copy);
ASSERT_EQ(sb.Count(), 2);
ASSERT_EQ(sb.Length(), 2 * kNewSliceLength + 1);
sb.Clear();
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -888,6 +888,8 @@ include/grpc/event_engine/internal/memory_allocator_impl.h \
include/grpc/event_engine/memory_allocator.h \
include/grpc/event_engine/memory_request.h \
include/grpc/event_engine/port.h \
include/grpc/event_engine/slice.h \
include/grpc/event_engine/slice_buffer.h \
include/grpc/fork.h \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \

@ -888,6 +888,8 @@ include/grpc/event_engine/internal/memory_allocator_impl.h \
include/grpc/event_engine/memory_allocator.h \
include/grpc/event_engine/memory_request.h \
include/grpc/event_engine/port.h \
include/grpc/event_engine/slice.h \
include/grpc/event_engine/slice_buffer.h \
include/grpc/fork.h \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \
@ -1933,6 +1935,8 @@ src/core/lib/event_engine/event_engine.cc \
src/core/lib/event_engine/event_engine_factory.h \
src/core/lib/event_engine/memory_allocator.cc \
src/core/lib/event_engine/resolved_address.cc \
src/core/lib/event_engine/slice.cc \
src/core/lib/event_engine/slice_buffer.cc \
src/core/lib/event_engine/sockaddr.cc \
src/core/lib/event_engine/sockaddr.h \
src/core/lib/gpr/alloc.cc \

@ -818,6 +818,8 @@ include/grpc/event_engine/internal/memory_allocator_impl.h \
include/grpc/event_engine/memory_allocator.h \
include/grpc/event_engine/memory_request.h \
include/grpc/event_engine/port.h \
include/grpc/event_engine/slice.h \
include/grpc/event_engine/slice_buffer.h \
include/grpc/fork.h \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \

@ -818,6 +818,8 @@ include/grpc/event_engine/internal/memory_allocator_impl.h \
include/grpc/event_engine/memory_allocator.h \
include/grpc/event_engine/memory_request.h \
include/grpc/event_engine/port.h \
include/grpc/event_engine/slice.h \
include/grpc/event_engine/slice_buffer.h \
include/grpc/fork.h \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \
@ -1725,6 +1727,8 @@ src/core/lib/event_engine/event_engine.cc \
src/core/lib/event_engine/event_engine_factory.h \
src/core/lib/event_engine/memory_allocator.cc \
src/core/lib/event_engine/resolved_address.cc \
src/core/lib/event_engine/slice.cc \
src/core/lib/event_engine/slice_buffer.cc \
src/core/lib/event_engine/sockaddr.cc \
src/core/lib/event_engine/sockaddr.h \
src/core/lib/gpr/README.md \

@ -1961,30 +1961,6 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "slice_buffer_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
@ -2333,6 +2309,30 @@
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "test_core_slice_slice_buffer_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
@ -6853,6 +6853,30 @@
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "test_core_event_engine_slice_buffer_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save