From 4f2b0fdadfb1e1eb6c796c40ec5aabfbb348aa89 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 19 Jan 2018 12:12:23 -0800 Subject: Rename 'gpr++' directories to 'gprpp'. --- src/core/ext/filters/client_channel/lb_policy.h | 2 +- .../client_channel/lb_policy/grpclb/grpclb.cc | 2 +- .../lb_policy/round_robin/round_robin.cc | 2 +- .../client_channel/lb_policy/subchannel_list.h | 2 +- .../resolver/dns/c_ares/dns_resolver_ares.cc | 2 +- .../resolver/dns/native/dns_resolver.cc | 2 +- src/core/ext/filters/client_channel/subchannel.cc | 4 +- src/core/ext/filters/client_channel/subchannel.h | 4 +- .../ext/transport/chttp2/transport/flow_control.h | 4 +- src/core/ext/transport/chttp2/transport/internal.h | 2 +- src/core/lib/gpr++/README.md | 16 -- src/core/lib/gpr++/abstract.h | 34 ---- src/core/lib/gpr++/atomic.h | 30 --- src/core/lib/gpr++/atomic_with_atm.h | 55 ------ src/core/lib/gpr++/atomic_with_std.h | 33 ---- src/core/lib/gpr++/debug_location.h | 52 ----- src/core/lib/gpr++/inlined_vector.h | 112 ----------- src/core/lib/gpr++/manual_constructor.h | 211 --------------------- src/core/lib/gpr++/memory.h | 100 ---------- src/core/lib/gpr++/orphanable.h | 171 ----------------- src/core/lib/gpr++/ref_counted.h | 133 ------------- src/core/lib/gpr++/ref_counted_ptr.h | 99 ---------- src/core/lib/gprpp/README.md | 16 ++ src/core/lib/gprpp/abstract.h | 34 ++++ src/core/lib/gprpp/atomic.h | 30 +++ src/core/lib/gprpp/atomic_with_atm.h | 55 ++++++ src/core/lib/gprpp/atomic_with_std.h | 33 ++++ src/core/lib/gprpp/debug_location.h | 52 +++++ src/core/lib/gprpp/inlined_vector.h | 112 +++++++++++ src/core/lib/gprpp/manual_constructor.h | 211 +++++++++++++++++++++ src/core/lib/gprpp/memory.h | 100 ++++++++++ src/core/lib/gprpp/orphanable.h | 171 +++++++++++++++++ src/core/lib/gprpp/ref_counted.h | 133 +++++++++++++ src/core/lib/gprpp/ref_counted_ptr.h | 99 ++++++++++ src/core/lib/iomgr/ev_epoll1_linux.cc | 2 +- src/core/lib/iomgr/ev_epollex_linux.cc | 2 +- src/core/lib/iomgr/ev_epollsig_linux.cc | 2 +- src/core/lib/surface/lame_client.cc | 2 +- 38 files changed, 1063 insertions(+), 1063 deletions(-) delete mode 100644 src/core/lib/gpr++/README.md delete mode 100644 src/core/lib/gpr++/abstract.h delete mode 100644 src/core/lib/gpr++/atomic.h delete mode 100644 src/core/lib/gpr++/atomic_with_atm.h delete mode 100644 src/core/lib/gpr++/atomic_with_std.h delete mode 100644 src/core/lib/gpr++/debug_location.h delete mode 100644 src/core/lib/gpr++/inlined_vector.h delete mode 100644 src/core/lib/gpr++/manual_constructor.h delete mode 100644 src/core/lib/gpr++/memory.h delete mode 100644 src/core/lib/gpr++/orphanable.h delete mode 100644 src/core/lib/gpr++/ref_counted.h delete mode 100644 src/core/lib/gpr++/ref_counted_ptr.h create mode 100644 src/core/lib/gprpp/README.md create mode 100644 src/core/lib/gprpp/abstract.h create mode 100644 src/core/lib/gprpp/atomic.h create mode 100644 src/core/lib/gprpp/atomic_with_atm.h create mode 100644 src/core/lib/gprpp/atomic_with_std.h create mode 100644 src/core/lib/gprpp/debug_location.h create mode 100644 src/core/lib/gprpp/inlined_vector.h create mode 100644 src/core/lib/gprpp/manual_constructor.h create mode 100644 src/core/lib/gprpp/memory.h create mode 100644 src/core/lib/gprpp/orphanable.h create mode 100644 src/core/lib/gprpp/ref_counted.h create mode 100644 src/core/lib/gprpp/ref_counted_ptr.h (limited to 'src') diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h index e19726efb3..30660cb83d 100644 --- a/src/core/ext/filters/client_channel/lb_policy.h +++ b/src/core/ext/filters/client_channel/lb_policy.h @@ -20,7 +20,7 @@ #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H #include "src/core/ext/filters/client_channel/subchannel.h" -#include "src/core/lib/gpr++/ref_counted_ptr.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/transport/connectivity_state.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index eb5ced4c20..b89a28c077 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -106,8 +106,8 @@ #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/gpr++/manual_constructor.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index e217a0b0c0..24c381a46d 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -34,7 +34,7 @@ #include "src/core/ext/filters/client_channel/subchannel_index.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gpr++/ref_counted_ptr.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index f4e345def6..3377605263 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -22,7 +22,7 @@ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gpr++/ref_counted_ptr.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/transport/connectivity_state.h" // TODO(roth): This code is intended to be shared between pick_first and diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 7ea3cdd6e1..9024ffb092 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -34,9 +34,9 @@ #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr++/manual_constructor.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/gethostname.h" #include "src/core/lib/iomgr/resolve_address.h" diff --git a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc index 93a1fe87a2..5aa7e6cc7e 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc @@ -29,9 +29,9 @@ #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr++/manual_constructor.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/timer.h" diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index fe4fcbbb7d..3edefaae64 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -37,8 +37,8 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/debug/stats.h" -#include "src/core/lib/gpr++/debug_location.h" -#include "src/core/lib/gpr++/manual_constructor.h" +#include "src/core/lib/gprpp/debug_location.h" +#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index f2a5c1e273..b7593ec911 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -21,9 +21,9 @@ #include "src/core/ext/filters/client_channel/connector.h" #include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/gpr++/ref_counted.h" -#include "src/core/lib/gpr++/ref_counted_ptr.h" #include "src/core/lib/gpr/arena.h" +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/metadata.h" diff --git a/src/core/ext/transport/chttp2/transport/flow_control.h b/src/core/ext/transport/chttp2/transport/flow_control.h index 7e83ea05cd..2ee1345260 100644 --- a/src/core/ext/transport/chttp2/transport/flow_control.h +++ b/src/core/ext/transport/chttp2/transport/flow_control.h @@ -24,8 +24,8 @@ #include #include "src/core/ext/transport/chttp2/transport/http2_settings.h" -#include "src/core/lib/gpr++/abstract.h" -#include "src/core/lib/gpr++/manual_constructor.h" +#include "src/core/lib/gprpp/abstract.h" +#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/transport/bdp_estimator.h" #include "src/core/lib/transport/pid_controller.h" diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index de901f0ce8..6b6c0b28e2 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -35,7 +35,7 @@ #include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" #include "src/core/ext/transport/chttp2/transport/stream_map.h" #include "src/core/lib/compression/stream_compression.h" -#include "src/core/lib/gpr++/manual_constructor.h" +#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/timer.h" diff --git a/src/core/lib/gpr++/README.md b/src/core/lib/gpr++/README.md deleted file mode 100644 index eab018bb31..0000000000 --- a/src/core/lib/gpr++/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# GPR++ - Google Portable Runtime for C++ - -The files in this directory contain various utility code for C++ code. -None of this code is gRPC-specific; anything here may also be useful -for other open source projects written in C++. - -Note that this is one of the few places in src/core where we allow -the use of portability macros. - -Note that this is the only place in src/core where we allow -use of the C++ standard library (i.e., anything in the `std::` -namespace). And for now, we require that any use of the -standard library is build-time-only -- i.e., we do not allow -run-time dependencies on libstdc++. For more details, see -[gRFC L6](/grpc/proposal/blob/master/L6-allow-c%2B%2B-in-grpc-core.md) and -[Moving gRPC core to C++](/grpc/grpc/blob/master/doc/core/moving-to-c%2B%2B.md). diff --git a/src/core/lib/gpr++/abstract.h b/src/core/lib/gpr++/abstract.h deleted file mode 100644 index 51d7572302..0000000000 --- a/src/core/lib/gpr++/abstract.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_ABSTRACT_H -#define GRPC_CORE_LIB_GPRXX_ABSTRACT_H - -// This is needed to support abstract base classes in the c core. Since gRPC -// doesn't have a c++ runtime, it will hit a linker error on delete unless -// we define a virtual operator delete. See this blog for more info: -// https://eli.thegreenplace.net/2015/c-deleting-destructors-and-virtual-operator-delete/ -#define GRPC_ABSTRACT_BASE_CLASS \ - static void operator delete(void* p) { abort(); } - -// gRPC currently can't depend on libstdc++, so we can't use "= 0" for -// pure virtual methods. Instead, we use this macro. -#define GRPC_ABSTRACT \ - { GPR_ASSERT(false); } - -#endif /* GRPC_CORE_LIB_GPRXX_ABSTRACT_H */ diff --git a/src/core/lib/gpr++/atomic.h b/src/core/lib/gpr++/atomic.h deleted file mode 100644 index d68ccea864..0000000000 --- a/src/core/lib/gpr++/atomic.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_ATOMIC_H -#define GRPC_CORE_LIB_GPRXX_ATOMIC_H - -#include - -#ifdef GPR_HAS_CXX11_ATOMIC -#include "src/core/lib/gpr++/atomic_with_std.h" -#else -#include "src/core/lib/gpr++/atomic_with_atm.h" -#endif - -#endif /* GRPC_CORE_LIB_GPRXX_ATOMIC_H */ diff --git a/src/core/lib/gpr++/atomic_with_atm.h b/src/core/lib/gpr++/atomic_with_atm.h deleted file mode 100644 index 09490e8148..0000000000 --- a/src/core/lib/gpr++/atomic_with_atm.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_ATOMIC_WITH_ATM_H -#define GRPC_CORE_LIB_GPRXX_ATOMIC_WITH_ATM_H - -#include - -namespace grpc_core { - -enum MemoryOrderRelaxed { memory_order_relaxed }; - -template -class atomic; - -template <> -class atomic { - public: - atomic() { gpr_atm_no_barrier_store(&x_, static_cast(false)); } - explicit atomic(bool x) { - gpr_atm_no_barrier_store(&x_, static_cast(x)); - } - - bool compare_exchange_strong(bool& expected, bool update, MemoryOrderRelaxed, - MemoryOrderRelaxed) { - if (!gpr_atm_no_barrier_cas(&x_, static_cast(expected), - static_cast(update))) { - expected = gpr_atm_no_barrier_load(&x_) != 0; - return false; - } - return true; - } - - private: - gpr_atm x_; -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRXX_ATOMIC_WITH_ATM_H */ diff --git a/src/core/lib/gpr++/atomic_with_std.h b/src/core/lib/gpr++/atomic_with_std.h deleted file mode 100644 index b6ff90655e..0000000000 --- a/src/core/lib/gpr++/atomic_with_std.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_ATOMIC_WITH_STD_H -#define GRPC_CORE_LIB_GPRXX_ATOMIC_WITH_STD_H - -#include - -namespace grpc_core { - -template -using atomic = std::atomic; - -typedef std::memory_order memory_order; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRXX_ATOMIC_WITH_STD_H */ diff --git a/src/core/lib/gpr++/debug_location.h b/src/core/lib/gpr++/debug_location.h deleted file mode 100644 index 5a8665ce19..0000000000 --- a/src/core/lib/gpr++/debug_location.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_DEBUG_LOCATION_H -#define GRPC_CORE_LIB_GPRXX_DEBUG_LOCATION_H - -namespace grpc_core { - -// Used for tracking file and line where a call is made for debug builds. -// No-op for non-debug builds. -// Callers can use the DEBUG_LOCATION macro in either case. -#ifndef NDEBUG -class DebugLocation { - public: - DebugLocation(const char* file, int line) : file_(file), line_(line) {} - bool Log() const { return true; } - const char* file() const { return file_; } - int line() const { return line_; } - - private: - const char* file_; - const int line_; -}; -#define DEBUG_LOCATION ::grpc_core::DebugLocation(__FILE__, __LINE__) -#else -class DebugLocation { - public: - bool Log() const { return false; } - const char* file() const { return nullptr; } - int line() const { return -1; } -}; -#define DEBUG_LOCATION ::grpc_core::DebugLocation() -#endif - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRXX_DEBUG_LOCATION_H */ diff --git a/src/core/lib/gpr++/inlined_vector.h b/src/core/lib/gpr++/inlined_vector.h deleted file mode 100644 index 17ee9e16bb..0000000000 --- a/src/core/lib/gpr++/inlined_vector.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_INLINED_VECTOR_H -#define GRPC_CORE_LIB_GPRXX_INLINED_VECTOR_H - -#include - -#include "src/core/lib/gpr++/memory.h" - -namespace grpc_core { - -// NOTE: We eventually want to use absl::InlinedVector here. However, -// there are currently build problems that prevent us from using absl. -// In the interim, we define a custom implementation as a place-holder, -// with the intent to eventually replace this with the absl -// implementation. -// -// This place-holder implementation does not implement the full set of -// functionality from the absl version; it has just the methods that we -// currently happen to need in gRPC. If additional functionality is -// needed before this gets replaced with the absl version, it can be -// added, with the following proviso: -// -// ANY METHOD ADDED HERE MUST COMPLY WITH THE INTERFACE IN THE absl -// IMPLEMENTATION! -// -// TODO(ctiller, nnoble, roth): Replace this with absl::InlinedVector -// once we integrate absl into the gRPC build system in a usable way. -template -class InlinedVector { - public: - InlinedVector() {} - ~InlinedVector() { - for (size_t i = 0; i < size_ && i < N; ++i) { - T& value = *reinterpret_cast(inline_ + i); - value.~T(); - } - if (size_ > N) { // Avoid subtracting two signed values. - for (size_t i = 0; i < size_ - N; ++i) { - dynamic_[i].~T(); - } - } - gpr_free(dynamic_); - } - - // For now, we do not support copying. - InlinedVector(const InlinedVector&) = delete; - InlinedVector& operator=(const InlinedVector&) = delete; - - T& operator[](size_t offset) { - assert(offset < size_); - if (offset < N) { - return *reinterpret_cast(inline_ + offset); - } else { - return dynamic_[offset - N]; - } - } - - template - void emplace_back(Args&&... args) { - if (size_ < N) { - new (&inline_[size_]) T(std::forward(args)...); - } else { - if (size_ - N == dynamic_capacity_) { - size_t new_capacity = - dynamic_capacity_ == 0 ? 2 : dynamic_capacity_ * 2; - T* new_dynamic = static_cast(gpr_malloc(sizeof(T) * new_capacity)); - for (size_t i = 0; i < dynamic_capacity_; ++i) { - new (&new_dynamic[i]) T(std::move(dynamic_[i])); - dynamic_[i].~T(); - } - gpr_free(dynamic_); - dynamic_ = new_dynamic; - dynamic_capacity_ = new_capacity; - } - new (&dynamic_[size_ - N]) T(std::forward(args)...); - } - ++size_; - } - - void push_back(const T& value) { emplace_back(value); } - - void push_back(T&& value) { emplace_back(std::move(value)); } - - size_t size() const { return size_; } - - private: - typename std::aligned_storage::type inline_[N]; - T* dynamic_ = nullptr; - size_t size_ = 0; - size_t dynamic_capacity_ = 0; -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRXX_INLINED_VECTOR_H */ diff --git a/src/core/lib/gpr++/manual_constructor.h b/src/core/lib/gpr++/manual_constructor.h deleted file mode 100644 index a3f006da34..0000000000 --- a/src/core/lib/gpr++/manual_constructor.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * - * Copyright 2016 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_CORE_LIB_GPRXX_MANUAL_CONSTRUCTOR_H -#define GRPC_CORE_LIB_GPRXX_MANUAL_CONSTRUCTOR_H - -// manually construct a region of memory with some type - -#include -#include -#include -#include -#include - -#include - -namespace grpc_core { - -// this contains templated helpers needed to implement the ManualConstructors -// in this file. -namespace manual_ctor_impl { - -// is_one_of returns true it a class, Member, is present in a variadic list of -// classes, List. -template -class is_one_of; - -template -class is_one_of { - public: - static constexpr const bool value = true; -}; - -template -class is_one_of { - public: - static constexpr const bool value = is_one_of::value; -}; - -template -class is_one_of { - public: - static constexpr const bool value = false; -}; - -// max_size_of returns sizeof(Type) for the largest type in the variadic list -// of classes, Types. -template -class max_size_of; - -template -class max_size_of { - public: - static constexpr const size_t value = sizeof(A); -}; - -template -class max_size_of { - public: - static constexpr const size_t value = sizeof(A) > max_size_of::value - ? sizeof(A) - : max_size_of::value; -}; - -// max_size_of returns alignof(Type) for the largest type in the variadic list -// of classes, Types. -template -class max_align_of; - -template -class max_align_of { - public: - static constexpr const size_t value = alignof(A); -}; - -template -class max_align_of { - public: - static constexpr const size_t value = alignof(A) > max_align_of::value - ? alignof(A) - : max_align_of::value; -}; - -} // namespace manual_ctor_impl - -template -class PolymorphicManualConstructor { - public: - // No constructor or destructor because one of the most useful uses of - // this class is as part of a union, and members of a union could not have - // constructors or destructors till C++11. And, anyway, the whole point of - // this class is to bypass constructor and destructor. - - BaseType* get() { return reinterpret_cast(&space_); } - const BaseType* get() const { - return reinterpret_cast(&space_); - } - - BaseType* operator->() { return get(); } - const BaseType* operator->() const { return get(); } - - BaseType& operator*() { return *get(); } - const BaseType& operator*() const { return *get(); } - - template - void Init() { - FinishInit(new (&space_) DerivedType); - } - - // Init() constructs the Type instance using the given arguments - // (which are forwarded to Type's constructor). - // - // Note that Init() with no arguments performs default-initialization, - // not zero-initialization (i.e it behaves the same as "new Type;", not - // "new Type();"), so it will leave non-class types uninitialized. - template - void Init(Ts&&... args) { - FinishInit(new (&space_) DerivedType(std::forward(args)...)); - } - - // Init() that is equivalent to copy and move construction. - // Enables usage like this: - // ManualConstructor> v; - // v.Init({1, 2, 3}); - template - void Init(const DerivedType& x) { - FinishInit(new (&space_) DerivedType(x)); - } - template - void Init(DerivedType&& x) { - FinishInit(new (&space_) DerivedType(std::move(x))); - } - - void Destroy() { get()->~BaseType(); } - - private: - template - void FinishInit(DerivedType* p) { - static_assert( - manual_ctor_impl::is_one_of::value, - "DerivedType must be one of the predeclared DerivedTypes"); - GPR_ASSERT(reinterpret_cast(static_cast(p)) == p); - } - - typename std::aligned_storage< - grpc_core::manual_ctor_impl::max_size_of::value, - grpc_core::manual_ctor_impl::max_align_of::value>::type - space_; -}; - -template -class ManualConstructor { - public: - // No constructor or destructor because one of the most useful uses of - // this class is as part of a union, and members of a union could not have - // constructors or destructors till C++11. And, anyway, the whole point of - // this class is to bypass constructor and destructor. - - Type* get() { return reinterpret_cast(&space_); } - const Type* get() const { return reinterpret_cast(&space_); } - - Type* operator->() { return get(); } - const Type* operator->() const { return get(); } - - Type& operator*() { return *get(); } - const Type& operator*() const { return *get(); } - - void Init() { new (&space_) Type; } - - // Init() constructs the Type instance using the given arguments - // (which are forwarded to Type's constructor). - // - // Note that Init() with no arguments performs default-initialization, - // not zero-initialization (i.e it behaves the same as "new Type;", not - // "new Type();"), so it will leave non-class types uninitialized. - template - void Init(Ts&&... args) { - new (&space_) Type(std::forward(args)...); - } - - // Init() that is equivalent to copy and move construction. - // Enables usage like this: - // ManualConstructor> v; - // v.Init({1, 2, 3}); - void Init(const Type& x) { new (&space_) Type(x); } - void Init(Type&& x) { new (&space_) Type(std::move(x)); } - - void Destroy() { get()->~Type(); } - - private: - typename std::aligned_storage::type space_; -}; - -} // namespace grpc_core - -#endif diff --git a/src/core/lib/gpr++/memory.h b/src/core/lib/gpr++/memory.h deleted file mode 100644 index 75ed3d6cea..0000000000 --- a/src/core/lib/gpr++/memory.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_MEMORY_H -#define GRPC_CORE_LIB_GPRXX_MEMORY_H - -#include - -#include -#include -#include - -namespace grpc_core { - -// Alternative to new, since we cannot use it (for fear of libstdc++) -template -inline T* New(Args&&... args) { - void* p = gpr_malloc(sizeof(T)); - return new (p) T(std::forward(args)...); -} - -// Alternative to delete, since we cannot use it (for fear of libstdc++) -template -inline void Delete(T* p) { - p->~T(); - gpr_free(p); -} - -template -class DefaultDelete { - public: - void operator()(T* p) { Delete(p); } -}; - -template > -using UniquePtr = std::unique_ptr; - -template -inline UniquePtr MakeUnique(Args&&... args) { - return UniquePtr(New(std::forward(args)...)); -} - -// an allocator that uses gpr_malloc/gpr_free -template -class Allocator { - public: - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::false_type propagate_on_container_move_assignment; - template - struct rebind { - typedef Allocator other; - }; - typedef std::true_type is_always_equal; - - pointer address(reference x) const { return &x; } - const_pointer address(const_reference x) const { return &x; } - pointer allocate(std::size_t n, - std::allocator::const_pointer hint = nullptr) { - return static_cast(gpr_malloc(n * sizeof(T))); - } - void deallocate(T* p, std::size_t n) { gpr_free(p); } - size_t max_size() const { - return std::numeric_limits::max() / sizeof(value_type); - } - void construct(pointer p, const_reference val) { new ((void*)p) T(val); } - template - void construct(U* p, Args&&... args) { - ::new ((void*)p) U(std::forward(args)...); - } - void destroy(pointer p) { p->~T(); } - template - void destroy(U* p) { - p->~U(); - } -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRXX_MEMORY_H */ diff --git a/src/core/lib/gpr++/orphanable.h b/src/core/lib/gpr++/orphanable.h deleted file mode 100644 index f106e74dde..0000000000 --- a/src/core/lib/gpr++/orphanable.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_ORPHANABLE_H -#define GRPC_CORE_LIB_GPRXX_ORPHANABLE_H - -#include -#include - -#include - -#include "src/core/lib/debug/trace.h" -#include "src/core/lib/gpr++/abstract.h" -#include "src/core/lib/gpr++/debug_location.h" -#include "src/core/lib/gpr++/memory.h" - -namespace grpc_core { - -// A base class for orphanable objects, which have one external owner -// but are not necessarily destroyed immediately when the external owner -// gives up ownership. Instead, the owner calls the object's Orphan() -// method, and the object then takes responsibility for its own cleanup -// and destruction. -class Orphanable { - public: - // Gives up ownership of the object. The implementation must arrange - // to eventually destroy the object without further interaction from the - // caller. - virtual void Orphan() GRPC_ABSTRACT; - - // Not copyable or movable. - Orphanable(const Orphanable&) = delete; - Orphanable& operator=(const Orphanable&) = delete; - - GRPC_ABSTRACT_BASE_CLASS - - protected: - Orphanable() {} - virtual ~Orphanable() {} -}; - -template -class OrphanableDelete { - public: - void operator()(T* p) { p->Orphan(); } -}; - -template > -using OrphanablePtr = std::unique_ptr; - -template -inline OrphanablePtr MakeOrphanable(Args&&... args) { - return OrphanablePtr(New(std::forward(args)...)); -} - -// A type of Orphanable with internal ref-counting. -class InternallyRefCounted : public Orphanable { - public: - // Not copyable nor movable. - InternallyRefCounted(const InternallyRefCounted&) = delete; - InternallyRefCounted& operator=(const InternallyRefCounted&) = delete; - - GRPC_ABSTRACT_BASE_CLASS - - protected: - InternallyRefCounted() { gpr_ref_init(&refs_, 1); } - virtual ~InternallyRefCounted() {} - - void Ref() { gpr_ref(&refs_); } - - void Unref() { - if (gpr_unref(&refs_)) { - Delete(this); - } - } - - // Allow Delete() to access destructor. - template - friend void Delete(T*); - - private: - gpr_refcount refs_; -}; - -// An alternative version of the InternallyRefCounted base class that -// supports tracing. This is intended to be used in cases where the -// object will be handled both by idiomatic C++ code using smart -// pointers and legacy code that is manually calling Ref() and Unref(). -// Once all of our code is converted to idiomatic C++, we may be able to -// eliminate this class. -class InternallyRefCountedWithTracing : public Orphanable { - public: - // Not copyable nor movable. - InternallyRefCountedWithTracing(const InternallyRefCountedWithTracing&) = - delete; - InternallyRefCountedWithTracing& operator=( - const InternallyRefCountedWithTracing&) = delete; - - GRPC_ABSTRACT_BASE_CLASS - - protected: - // Allow Delete() to access destructor. - template - friend void Delete(T*); - - InternallyRefCountedWithTracing() - : InternallyRefCountedWithTracing(static_cast(nullptr)) {} - - explicit InternallyRefCountedWithTracing(TraceFlag* trace_flag) - : trace_flag_(trace_flag) { - gpr_ref_init(&refs_, 1); - } - -#ifdef NDEBUG - explicit InternallyRefCountedWithTracing(DebugOnlyTraceFlag* trace_flag) - : InternallyRefCountedWithTracing() {} -#endif - - virtual ~InternallyRefCountedWithTracing() {} - - void Ref() { gpr_ref(&refs_); } - - void Ref(const DebugLocation& location, const char* reason) { - if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); - gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", - trace_flag_->name(), this, location.file(), location.line(), - old_refs, old_refs + 1, reason); - } - Ref(); - } - - void Unref() { - if (gpr_unref(&refs_)) { - Delete(this); - } - } - - void Unref(const DebugLocation& location, const char* reason) { - if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); - gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", - trace_flag_->name(), this, location.file(), location.line(), - old_refs, old_refs - 1, reason); - } - Unref(); - } - - private: - TraceFlag* trace_flag_ = nullptr; - gpr_refcount refs_; -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRXX_ORPHANABLE_H */ diff --git a/src/core/lib/gpr++/ref_counted.h b/src/core/lib/gpr++/ref_counted.h deleted file mode 100644 index c2ae76c0ae..0000000000 --- a/src/core/lib/gpr++/ref_counted.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_REF_COUNTED_H -#define GRPC_CORE_LIB_GPRXX_REF_COUNTED_H - -#include -#include - -#include "src/core/lib/debug/trace.h" -#include "src/core/lib/gpr++/abstract.h" -#include "src/core/lib/gpr++/debug_location.h" -#include "src/core/lib/gpr++/memory.h" - -namespace grpc_core { - -// A base class for reference-counted objects. -// New objects should be created via New() and start with a refcount of 1. -// When the refcount reaches 0, the object will be deleted via Delete(). -class RefCounted { - public: - void Ref() { gpr_ref(&refs_); } - - void Unref() { - if (gpr_unref(&refs_)) { - Delete(this); - } - } - - // Not copyable nor movable. - RefCounted(const RefCounted&) = delete; - RefCounted& operator=(const RefCounted&) = delete; - - GRPC_ABSTRACT_BASE_CLASS - - protected: - // Allow Delete() to access destructor. - template - friend void Delete(T*); - - RefCounted() { gpr_ref_init(&refs_, 1); } - - virtual ~RefCounted() {} - - private: - gpr_refcount refs_; -}; - -// An alternative version of the RefCounted base class that -// supports tracing. This is intended to be used in cases where the -// object will be handled both by idiomatic C++ code using smart -// pointers and legacy code that is manually calling Ref() and Unref(). -// Once all of our code is converted to idiomatic C++, we may be able to -// eliminate this class. -class RefCountedWithTracing { - public: - void Ref() { gpr_ref(&refs_); } - - void Ref(const DebugLocation& location, const char* reason) { - if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); - gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", - trace_flag_->name(), this, location.file(), location.line(), - old_refs, old_refs + 1, reason); - } - Ref(); - } - - void Unref() { - if (gpr_unref(&refs_)) { - Delete(this); - } - } - - void Unref(const DebugLocation& location, const char* reason) { - if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); - gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", - trace_flag_->name(), this, location.file(), location.line(), - old_refs, old_refs - 1, reason); - } - Unref(); - } - - // Not copyable nor movable. - RefCountedWithTracing(const RefCountedWithTracing&) = delete; - RefCountedWithTracing& operator=(const RefCountedWithTracing&) = delete; - - GRPC_ABSTRACT_BASE_CLASS - - protected: - // Allow Delete() to access destructor. - template - friend void Delete(T*); - - RefCountedWithTracing() - : RefCountedWithTracing(static_cast(nullptr)) {} - - explicit RefCountedWithTracing(TraceFlag* trace_flag) - : trace_flag_(trace_flag) { - gpr_ref_init(&refs_, 1); - } - -#ifdef NDEBUG - explicit RefCountedWithTracing(DebugOnlyTraceFlag* trace_flag) - : RefCountedWithTracing() {} -#endif - - virtual ~RefCountedWithTracing() {} - - private: - TraceFlag* trace_flag_ = nullptr; - gpr_refcount refs_; -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRXX_REF_COUNTED_H */ diff --git a/src/core/lib/gpr++/ref_counted_ptr.h b/src/core/lib/gpr++/ref_counted_ptr.h deleted file mode 100644 index 862294d1aa..0000000000 --- a/src/core/lib/gpr++/ref_counted_ptr.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * - * Copyright 2017 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_CORE_LIB_GPRXX_REF_COUNTED_PTR_H -#define GRPC_CORE_LIB_GPRXX_REF_COUNTED_PTR_H - -#include - -#include "src/core/lib/gpr++/memory.h" - -namespace grpc_core { - -// A smart pointer class for objects that provide Ref() and Unref() methods, -// such as those provided by the RefCounted base class. -template -class RefCountedPtr { - public: - RefCountedPtr() {} - - // If value is non-null, we take ownership of a ref to it. - explicit RefCountedPtr(T* value) { value_ = value; } - - // Move support. - RefCountedPtr(RefCountedPtr&& other) { - value_ = other.value_; - other.value_ = nullptr; - } - RefCountedPtr& operator=(RefCountedPtr&& other) { - if (value_ != nullptr) value_->Unref(); - value_ = other.value_; - other.value_ = nullptr; - return *this; - } - - // Copy support. - RefCountedPtr(const RefCountedPtr& other) { - if (other.value_ != nullptr) other.value_->Ref(); - value_ = other.value_; - } - RefCountedPtr& operator=(const RefCountedPtr& other) { - // Note: Order of reffing and unreffing is important here in case value_ - // and other.value_ are the same object. - if (other.value_ != nullptr) other.value_->Ref(); - if (value_ != nullptr) value_->Unref(); - value_ = other.value_; - return *this; - } - - ~RefCountedPtr() { - if (value_ != nullptr) value_->Unref(); - } - - // If value is non-null, we take ownership of a ref to it. - void reset(T* value = nullptr) { - if (value_ != nullptr) value_->Unref(); - value_ = value; - } - - T* get() const { return value_; } - - T& operator*() const { return *value_; } - T* operator->() const { return value_; } - - bool operator==(const RefCountedPtr& other) const { - return value_ == other.value_; - } - bool operator==(const T* other) const { return value_ == other; } - bool operator!=(const RefCountedPtr& other) const { - return value_ != other.value_; - } - bool operator!=(const T* other) const { return value_ != other; } - - private: - T* value_ = nullptr; -}; - -template -inline RefCountedPtr MakeRefCounted(Args&&... args) { - return RefCountedPtr(New(std::forward(args)...)); -} - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRXX_REF_COUNTED_PTR_H */ diff --git a/src/core/lib/gprpp/README.md b/src/core/lib/gprpp/README.md new file mode 100644 index 0000000000..eab018bb31 --- /dev/null +++ b/src/core/lib/gprpp/README.md @@ -0,0 +1,16 @@ +# GPR++ - Google Portable Runtime for C++ + +The files in this directory contain various utility code for C++ code. +None of this code is gRPC-specific; anything here may also be useful +for other open source projects written in C++. + +Note that this is one of the few places in src/core where we allow +the use of portability macros. + +Note that this is the only place in src/core where we allow +use of the C++ standard library (i.e., anything in the `std::` +namespace). And for now, we require that any use of the +standard library is build-time-only -- i.e., we do not allow +run-time dependencies on libstdc++. For more details, see +[gRFC L6](/grpc/proposal/blob/master/L6-allow-c%2B%2B-in-grpc-core.md) and +[Moving gRPC core to C++](/grpc/grpc/blob/master/doc/core/moving-to-c%2B%2B.md). diff --git a/src/core/lib/gprpp/abstract.h b/src/core/lib/gprpp/abstract.h new file mode 100644 index 0000000000..cc96edc49b --- /dev/null +++ b/src/core/lib/gprpp/abstract.h @@ -0,0 +1,34 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_ABSTRACT_H +#define GRPC_CORE_LIB_GPRPP_ABSTRACT_H + +// This is needed to support abstract base classes in the c core. Since gRPC +// doesn't have a c++ runtime, it will hit a linker error on delete unless +// we define a virtual operator delete. See this blog for more info: +// https://eli.thegreenplace.net/2015/c-deleting-destructors-and-virtual-operator-delete/ +#define GRPC_ABSTRACT_BASE_CLASS \ + static void operator delete(void* p) { abort(); } + +// gRPC currently can't depend on libstdc++, so we can't use "= 0" for +// pure virtual methods. Instead, we use this macro. +#define GRPC_ABSTRACT \ + { GPR_ASSERT(false); } + +#endif /* GRPC_CORE_LIB_GPRPP_ABSTRACT_H */ diff --git a/src/core/lib/gprpp/atomic.h b/src/core/lib/gprpp/atomic.h new file mode 100644 index 0000000000..8b08fc4e9c --- /dev/null +++ b/src/core/lib/gprpp/atomic.h @@ -0,0 +1,30 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_ATOMIC_H +#define GRPC_CORE_LIB_GPRPP_ATOMIC_H + +#include + +#ifdef GPR_HAS_CXX11_ATOMIC +#include "src/core/lib/gprpp/atomic_with_std.h" +#else +#include "src/core/lib/gprpp/atomic_with_atm.h" +#endif + +#endif /* GRPC_CORE_LIB_GPRPP_ATOMIC_H */ diff --git a/src/core/lib/gprpp/atomic_with_atm.h b/src/core/lib/gprpp/atomic_with_atm.h new file mode 100644 index 0000000000..6abf0bc38d --- /dev/null +++ b/src/core/lib/gprpp/atomic_with_atm.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_ATOMIC_WITH_ATM_H +#define GRPC_CORE_LIB_GPRPP_ATOMIC_WITH_ATM_H + +#include + +namespace grpc_core { + +enum MemoryOrderRelaxed { memory_order_relaxed }; + +template +class atomic; + +template <> +class atomic { + public: + atomic() { gpr_atm_no_barrier_store(&x_, static_cast(false)); } + explicit atomic(bool x) { + gpr_atm_no_barrier_store(&x_, static_cast(x)); + } + + bool compare_exchange_strong(bool& expected, bool update, MemoryOrderRelaxed, + MemoryOrderRelaxed) { + if (!gpr_atm_no_barrier_cas(&x_, static_cast(expected), + static_cast(update))) { + expected = gpr_atm_no_barrier_load(&x_) != 0; + return false; + } + return true; + } + + private: + gpr_atm x_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_ATOMIC_WITH_ATM_H */ diff --git a/src/core/lib/gprpp/atomic_with_std.h b/src/core/lib/gprpp/atomic_with_std.h new file mode 100644 index 0000000000..83322b81c1 --- /dev/null +++ b/src/core/lib/gprpp/atomic_with_std.h @@ -0,0 +1,33 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_ATOMIC_WITH_STD_H +#define GRPC_CORE_LIB_GPRPP_ATOMIC_WITH_STD_H + +#include + +namespace grpc_core { + +template +using atomic = std::atomic; + +typedef std::memory_order memory_order; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_ATOMIC_WITH_STD_H */ diff --git a/src/core/lib/gprpp/debug_location.h b/src/core/lib/gprpp/debug_location.h new file mode 100644 index 0000000000..287761beaf --- /dev/null +++ b/src/core/lib/gprpp/debug_location.h @@ -0,0 +1,52 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_DEBUG_LOCATION_H +#define GRPC_CORE_LIB_GPRPP_DEBUG_LOCATION_H + +namespace grpc_core { + +// Used for tracking file and line where a call is made for debug builds. +// No-op for non-debug builds. +// Callers can use the DEBUG_LOCATION macro in either case. +#ifndef NDEBUG +class DebugLocation { + public: + DebugLocation(const char* file, int line) : file_(file), line_(line) {} + bool Log() const { return true; } + const char* file() const { return file_; } + int line() const { return line_; } + + private: + const char* file_; + const int line_; +}; +#define DEBUG_LOCATION ::grpc_core::DebugLocation(__FILE__, __LINE__) +#else +class DebugLocation { + public: + bool Log() const { return false; } + const char* file() const { return nullptr; } + int line() const { return -1; } +}; +#define DEBUG_LOCATION ::grpc_core::DebugLocation() +#endif + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_DEBUG_LOCATION_H */ diff --git a/src/core/lib/gprpp/inlined_vector.h b/src/core/lib/gprpp/inlined_vector.h new file mode 100644 index 0000000000..b78f85b893 --- /dev/null +++ b/src/core/lib/gprpp/inlined_vector.h @@ -0,0 +1,112 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_INLINED_VECTOR_H +#define GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H + +#include + +#include "src/core/lib/gprpp/memory.h" + +namespace grpc_core { + +// NOTE: We eventually want to use absl::InlinedVector here. However, +// there are currently build problems that prevent us from using absl. +// In the interim, we define a custom implementation as a place-holder, +// with the intent to eventually replace this with the absl +// implementation. +// +// This place-holder implementation does not implement the full set of +// functionality from the absl version; it has just the methods that we +// currently happen to need in gRPC. If additional functionality is +// needed before this gets replaced with the absl version, it can be +// added, with the following proviso: +// +// ANY METHOD ADDED HERE MUST COMPLY WITH THE INTERFACE IN THE absl +// IMPLEMENTATION! +// +// TODO(ctiller, nnoble, roth): Replace this with absl::InlinedVector +// once we integrate absl into the gRPC build system in a usable way. +template +class InlinedVector { + public: + InlinedVector() {} + ~InlinedVector() { + for (size_t i = 0; i < size_ && i < N; ++i) { + T& value = *reinterpret_cast(inline_ + i); + value.~T(); + } + if (size_ > N) { // Avoid subtracting two signed values. + for (size_t i = 0; i < size_ - N; ++i) { + dynamic_[i].~T(); + } + } + gpr_free(dynamic_); + } + + // For now, we do not support copying. + InlinedVector(const InlinedVector&) = delete; + InlinedVector& operator=(const InlinedVector&) = delete; + + T& operator[](size_t offset) { + assert(offset < size_); + if (offset < N) { + return *reinterpret_cast(inline_ + offset); + } else { + return dynamic_[offset - N]; + } + } + + template + void emplace_back(Args&&... args) { + if (size_ < N) { + new (&inline_[size_]) T(std::forward(args)...); + } else { + if (size_ - N == dynamic_capacity_) { + size_t new_capacity = + dynamic_capacity_ == 0 ? 2 : dynamic_capacity_ * 2; + T* new_dynamic = static_cast(gpr_malloc(sizeof(T) * new_capacity)); + for (size_t i = 0; i < dynamic_capacity_; ++i) { + new (&new_dynamic[i]) T(std::move(dynamic_[i])); + dynamic_[i].~T(); + } + gpr_free(dynamic_); + dynamic_ = new_dynamic; + dynamic_capacity_ = new_capacity; + } + new (&dynamic_[size_ - N]) T(std::forward(args)...); + } + ++size_; + } + + void push_back(const T& value) { emplace_back(value); } + + void push_back(T&& value) { emplace_back(std::move(value)); } + + size_t size() const { return size_; } + + private: + typename std::aligned_storage::type inline_[N]; + T* dynamic_ = nullptr; + size_t size_ = 0; + size_t dynamic_capacity_ = 0; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_INLINED_VECTOR_H */ diff --git a/src/core/lib/gprpp/manual_constructor.h b/src/core/lib/gprpp/manual_constructor.h new file mode 100644 index 0000000000..cee38abc1b --- /dev/null +++ b/src/core/lib/gprpp/manual_constructor.h @@ -0,0 +1,211 @@ +/* + * + * Copyright 2016 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_CORE_LIB_GPRPP_MANUAL_CONSTRUCTOR_H +#define GRPC_CORE_LIB_GPRPP_MANUAL_CONSTRUCTOR_H + +// manually construct a region of memory with some type + +#include +#include +#include +#include +#include + +#include + +namespace grpc_core { + +// this contains templated helpers needed to implement the ManualConstructors +// in this file. +namespace manual_ctor_impl { + +// is_one_of returns true it a class, Member, is present in a variadic list of +// classes, List. +template +class is_one_of; + +template +class is_one_of { + public: + static constexpr const bool value = true; +}; + +template +class is_one_of { + public: + static constexpr const bool value = is_one_of::value; +}; + +template +class is_one_of { + public: + static constexpr const bool value = false; +}; + +// max_size_of returns sizeof(Type) for the largest type in the variadic list +// of classes, Types. +template +class max_size_of; + +template +class max_size_of { + public: + static constexpr const size_t value = sizeof(A); +}; + +template +class max_size_of { + public: + static constexpr const size_t value = sizeof(A) > max_size_of::value + ? sizeof(A) + : max_size_of::value; +}; + +// max_size_of returns alignof(Type) for the largest type in the variadic list +// of classes, Types. +template +class max_align_of; + +template +class max_align_of { + public: + static constexpr const size_t value = alignof(A); +}; + +template +class max_align_of { + public: + static constexpr const size_t value = alignof(A) > max_align_of::value + ? alignof(A) + : max_align_of::value; +}; + +} // namespace manual_ctor_impl + +template +class PolymorphicManualConstructor { + public: + // No constructor or destructor because one of the most useful uses of + // this class is as part of a union, and members of a union could not have + // constructors or destructors till C++11. And, anyway, the whole point of + // this class is to bypass constructor and destructor. + + BaseType* get() { return reinterpret_cast(&space_); } + const BaseType* get() const { + return reinterpret_cast(&space_); + } + + BaseType* operator->() { return get(); } + const BaseType* operator->() const { return get(); } + + BaseType& operator*() { return *get(); } + const BaseType& operator*() const { return *get(); } + + template + void Init() { + FinishInit(new (&space_) DerivedType); + } + + // Init() constructs the Type instance using the given arguments + // (which are forwarded to Type's constructor). + // + // Note that Init() with no arguments performs default-initialization, + // not zero-initialization (i.e it behaves the same as "new Type;", not + // "new Type();"), so it will leave non-class types uninitialized. + template + void Init(Ts&&... args) { + FinishInit(new (&space_) DerivedType(std::forward(args)...)); + } + + // Init() that is equivalent to copy and move construction. + // Enables usage like this: + // ManualConstructor> v; + // v.Init({1, 2, 3}); + template + void Init(const DerivedType& x) { + FinishInit(new (&space_) DerivedType(x)); + } + template + void Init(DerivedType&& x) { + FinishInit(new (&space_) DerivedType(std::move(x))); + } + + void Destroy() { get()->~BaseType(); } + + private: + template + void FinishInit(DerivedType* p) { + static_assert( + manual_ctor_impl::is_one_of::value, + "DerivedType must be one of the predeclared DerivedTypes"); + GPR_ASSERT(reinterpret_cast(static_cast(p)) == p); + } + + typename std::aligned_storage< + grpc_core::manual_ctor_impl::max_size_of::value, + grpc_core::manual_ctor_impl::max_align_of::value>::type + space_; +}; + +template +class ManualConstructor { + public: + // No constructor or destructor because one of the most useful uses of + // this class is as part of a union, and members of a union could not have + // constructors or destructors till C++11. And, anyway, the whole point of + // this class is to bypass constructor and destructor. + + Type* get() { return reinterpret_cast(&space_); } + const Type* get() const { return reinterpret_cast(&space_); } + + Type* operator->() { return get(); } + const Type* operator->() const { return get(); } + + Type& operator*() { return *get(); } + const Type& operator*() const { return *get(); } + + void Init() { new (&space_) Type; } + + // Init() constructs the Type instance using the given arguments + // (which are forwarded to Type's constructor). + // + // Note that Init() with no arguments performs default-initialization, + // not zero-initialization (i.e it behaves the same as "new Type;", not + // "new Type();"), so it will leave non-class types uninitialized. + template + void Init(Ts&&... args) { + new (&space_) Type(std::forward(args)...); + } + + // Init() that is equivalent to copy and move construction. + // Enables usage like this: + // ManualConstructor> v; + // v.Init({1, 2, 3}); + void Init(const Type& x) { new (&space_) Type(x); } + void Init(Type&& x) { new (&space_) Type(std::move(x)); } + + void Destroy() { get()->~Type(); } + + private: + typename std::aligned_storage::type space_; +}; + +} // namespace grpc_core + +#endif diff --git a/src/core/lib/gprpp/memory.h b/src/core/lib/gprpp/memory.h new file mode 100644 index 0000000000..17f42f5983 --- /dev/null +++ b/src/core/lib/gprpp/memory.h @@ -0,0 +1,100 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_MEMORY_H +#define GRPC_CORE_LIB_GPRPP_MEMORY_H + +#include + +#include +#include +#include + +namespace grpc_core { + +// Alternative to new, since we cannot use it (for fear of libstdc++) +template +inline T* New(Args&&... args) { + void* p = gpr_malloc(sizeof(T)); + return new (p) T(std::forward(args)...); +} + +// Alternative to delete, since we cannot use it (for fear of libstdc++) +template +inline void Delete(T* p) { + p->~T(); + gpr_free(p); +} + +template +class DefaultDelete { + public: + void operator()(T* p) { Delete(p); } +}; + +template > +using UniquePtr = std::unique_ptr; + +template +inline UniquePtr MakeUnique(Args&&... args) { + return UniquePtr(New(std::forward(args)...)); +} + +// an allocator that uses gpr_malloc/gpr_free +template +class Allocator { + public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::false_type propagate_on_container_move_assignment; + template + struct rebind { + typedef Allocator other; + }; + typedef std::true_type is_always_equal; + + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + pointer allocate(std::size_t n, + std::allocator::const_pointer hint = nullptr) { + return static_cast(gpr_malloc(n * sizeof(T))); + } + void deallocate(T* p, std::size_t n) { gpr_free(p); } + size_t max_size() const { + return std::numeric_limits::max() / sizeof(value_type); + } + void construct(pointer p, const_reference val) { new ((void*)p) T(val); } + template + void construct(U* p, Args&&... args) { + ::new ((void*)p) U(std::forward(args)...); + } + void destroy(pointer p) { p->~T(); } + template + void destroy(U* p) { + p->~U(); + } +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_MEMORY_H */ diff --git a/src/core/lib/gprpp/orphanable.h b/src/core/lib/gprpp/orphanable.h new file mode 100644 index 0000000000..50199730c9 --- /dev/null +++ b/src/core/lib/gprpp/orphanable.h @@ -0,0 +1,171 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_ORPHANABLE_H +#define GRPC_CORE_LIB_GPRPP_ORPHANABLE_H + +#include +#include + +#include + +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/abstract.h" +#include "src/core/lib/gprpp/debug_location.h" +#include "src/core/lib/gprpp/memory.h" + +namespace grpc_core { + +// A base class for orphanable objects, which have one external owner +// but are not necessarily destroyed immediately when the external owner +// gives up ownership. Instead, the owner calls the object's Orphan() +// method, and the object then takes responsibility for its own cleanup +// and destruction. +class Orphanable { + public: + // Gives up ownership of the object. The implementation must arrange + // to eventually destroy the object without further interaction from the + // caller. + virtual void Orphan() GRPC_ABSTRACT; + + // Not copyable or movable. + Orphanable(const Orphanable&) = delete; + Orphanable& operator=(const Orphanable&) = delete; + + GRPC_ABSTRACT_BASE_CLASS + + protected: + Orphanable() {} + virtual ~Orphanable() {} +}; + +template +class OrphanableDelete { + public: + void operator()(T* p) { p->Orphan(); } +}; + +template > +using OrphanablePtr = std::unique_ptr; + +template +inline OrphanablePtr MakeOrphanable(Args&&... args) { + return OrphanablePtr(New(std::forward(args)...)); +} + +// A type of Orphanable with internal ref-counting. +class InternallyRefCounted : public Orphanable { + public: + // Not copyable nor movable. + InternallyRefCounted(const InternallyRefCounted&) = delete; + InternallyRefCounted& operator=(const InternallyRefCounted&) = delete; + + GRPC_ABSTRACT_BASE_CLASS + + protected: + InternallyRefCounted() { gpr_ref_init(&refs_, 1); } + virtual ~InternallyRefCounted() {} + + void Ref() { gpr_ref(&refs_); } + + void Unref() { + if (gpr_unref(&refs_)) { + Delete(this); + } + } + + // Allow Delete() to access destructor. + template + friend void Delete(T*); + + private: + gpr_refcount refs_; +}; + +// An alternative version of the InternallyRefCounted base class that +// supports tracing. This is intended to be used in cases where the +// object will be handled both by idiomatic C++ code using smart +// pointers and legacy code that is manually calling Ref() and Unref(). +// Once all of our code is converted to idiomatic C++, we may be able to +// eliminate this class. +class InternallyRefCountedWithTracing : public Orphanable { + public: + // Not copyable nor movable. + InternallyRefCountedWithTracing(const InternallyRefCountedWithTracing&) = + delete; + InternallyRefCountedWithTracing& operator=( + const InternallyRefCountedWithTracing&) = delete; + + GRPC_ABSTRACT_BASE_CLASS + + protected: + // Allow Delete() to access destructor. + template + friend void Delete(T*); + + InternallyRefCountedWithTracing() + : InternallyRefCountedWithTracing(static_cast(nullptr)) {} + + explicit InternallyRefCountedWithTracing(TraceFlag* trace_flag) + : trace_flag_(trace_flag) { + gpr_ref_init(&refs_, 1); + } + +#ifdef NDEBUG + explicit InternallyRefCountedWithTracing(DebugOnlyTraceFlag* trace_flag) + : InternallyRefCountedWithTracing() {} +#endif + + virtual ~InternallyRefCountedWithTracing() {} + + void Ref() { gpr_ref(&refs_); } + + void Ref(const DebugLocation& location, const char* reason) { + if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { + gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); + gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", + trace_flag_->name(), this, location.file(), location.line(), + old_refs, old_refs + 1, reason); + } + Ref(); + } + + void Unref() { + if (gpr_unref(&refs_)) { + Delete(this); + } + } + + void Unref(const DebugLocation& location, const char* reason) { + if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { + gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); + gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", + trace_flag_->name(), this, location.file(), location.line(), + old_refs, old_refs - 1, reason); + } + Unref(); + } + + private: + TraceFlag* trace_flag_ = nullptr; + gpr_refcount refs_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_ORPHANABLE_H */ diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h new file mode 100644 index 0000000000..c68118a71a --- /dev/null +++ b/src/core/lib/gprpp/ref_counted.h @@ -0,0 +1,133 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_REF_COUNTED_H +#define GRPC_CORE_LIB_GPRPP_REF_COUNTED_H + +#include +#include + +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/abstract.h" +#include "src/core/lib/gprpp/debug_location.h" +#include "src/core/lib/gprpp/memory.h" + +namespace grpc_core { + +// A base class for reference-counted objects. +// New objects should be created via New() and start with a refcount of 1. +// When the refcount reaches 0, the object will be deleted via Delete(). +class RefCounted { + public: + void Ref() { gpr_ref(&refs_); } + + void Unref() { + if (gpr_unref(&refs_)) { + Delete(this); + } + } + + // Not copyable nor movable. + RefCounted(const RefCounted&) = delete; + RefCounted& operator=(const RefCounted&) = delete; + + GRPC_ABSTRACT_BASE_CLASS + + protected: + // Allow Delete() to access destructor. + template + friend void Delete(T*); + + RefCounted() { gpr_ref_init(&refs_, 1); } + + virtual ~RefCounted() {} + + private: + gpr_refcount refs_; +}; + +// An alternative version of the RefCounted base class that +// supports tracing. This is intended to be used in cases where the +// object will be handled both by idiomatic C++ code using smart +// pointers and legacy code that is manually calling Ref() and Unref(). +// Once all of our code is converted to idiomatic C++, we may be able to +// eliminate this class. +class RefCountedWithTracing { + public: + void Ref() { gpr_ref(&refs_); } + + void Ref(const DebugLocation& location, const char* reason) { + if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { + gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); + gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", + trace_flag_->name(), this, location.file(), location.line(), + old_refs, old_refs + 1, reason); + } + Ref(); + } + + void Unref() { + if (gpr_unref(&refs_)) { + Delete(this); + } + } + + void Unref(const DebugLocation& location, const char* reason) { + if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { + gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); + gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", + trace_flag_->name(), this, location.file(), location.line(), + old_refs, old_refs - 1, reason); + } + Unref(); + } + + // Not copyable nor movable. + RefCountedWithTracing(const RefCountedWithTracing&) = delete; + RefCountedWithTracing& operator=(const RefCountedWithTracing&) = delete; + + GRPC_ABSTRACT_BASE_CLASS + + protected: + // Allow Delete() to access destructor. + template + friend void Delete(T*); + + RefCountedWithTracing() + : RefCountedWithTracing(static_cast(nullptr)) {} + + explicit RefCountedWithTracing(TraceFlag* trace_flag) + : trace_flag_(trace_flag) { + gpr_ref_init(&refs_, 1); + } + +#ifdef NDEBUG + explicit RefCountedWithTracing(DebugOnlyTraceFlag* trace_flag) + : RefCountedWithTracing() {} +#endif + + virtual ~RefCountedWithTracing() {} + + private: + TraceFlag* trace_flag_ = nullptr; + gpr_refcount refs_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_REF_COUNTED_H */ diff --git a/src/core/lib/gprpp/ref_counted_ptr.h b/src/core/lib/gprpp/ref_counted_ptr.h new file mode 100644 index 0000000000..dda0f00d79 --- /dev/null +++ b/src/core/lib/gprpp/ref_counted_ptr.h @@ -0,0 +1,99 @@ +/* + * + * Copyright 2017 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_CORE_LIB_GPRPP_REF_COUNTED_PTR_H +#define GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H + +#include + +#include "src/core/lib/gprpp/memory.h" + +namespace grpc_core { + +// A smart pointer class for objects that provide Ref() and Unref() methods, +// such as those provided by the RefCounted base class. +template +class RefCountedPtr { + public: + RefCountedPtr() {} + + // If value is non-null, we take ownership of a ref to it. + explicit RefCountedPtr(T* value) { value_ = value; } + + // Move support. + RefCountedPtr(RefCountedPtr&& other) { + value_ = other.value_; + other.value_ = nullptr; + } + RefCountedPtr& operator=(RefCountedPtr&& other) { + if (value_ != nullptr) value_->Unref(); + value_ = other.value_; + other.value_ = nullptr; + return *this; + } + + // Copy support. + RefCountedPtr(const RefCountedPtr& other) { + if (other.value_ != nullptr) other.value_->Ref(); + value_ = other.value_; + } + RefCountedPtr& operator=(const RefCountedPtr& other) { + // Note: Order of reffing and unreffing is important here in case value_ + // and other.value_ are the same object. + if (other.value_ != nullptr) other.value_->Ref(); + if (value_ != nullptr) value_->Unref(); + value_ = other.value_; + return *this; + } + + ~RefCountedPtr() { + if (value_ != nullptr) value_->Unref(); + } + + // If value is non-null, we take ownership of a ref to it. + void reset(T* value = nullptr) { + if (value_ != nullptr) value_->Unref(); + value_ = value; + } + + T* get() const { return value_; } + + T& operator*() const { return *value_; } + T* operator->() const { return value_; } + + bool operator==(const RefCountedPtr& other) const { + return value_ == other.value_; + } + bool operator==(const T* other) const { return value_ == other; } + bool operator!=(const RefCountedPtr& other) const { + return value_ != other.value_; + } + bool operator!=(const T* other) const { return value_ != other; } + + private: + T* value_ = nullptr; +}; + +template +inline RefCountedPtr MakeRefCounted(Args&&... args) { + return RefCountedPtr(New(std::forward(args)...)); +} + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H */ diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc index 1cb0150f45..42d7cdd348 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.cc +++ b/src/core/lib/iomgr/ev_epoll1_linux.cc @@ -43,8 +43,8 @@ #include #include "src/core/lib/debug/stats.h" -#include "src/core/lib/gpr++/manual_constructor.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/block_annotate.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index b81c00ca7a..416e8384b4 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -41,8 +41,8 @@ #include #include "src/core/lib/debug/stats.h" -#include "src/core/lib/gpr++/manual_constructor.h" #include "src/core/lib/gpr/spinlock.h" +#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/block_annotate.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/is_epollexclusive_available.h" diff --git a/src/core/lib/iomgr/ev_epollsig_linux.cc b/src/core/lib/iomgr/ev_epollsig_linux.cc index 11c64d080c..1518348992 100644 --- a/src/core/lib/iomgr/ev_epollsig_linux.cc +++ b/src/core/lib/iomgr/ev_epollsig_linux.cc @@ -43,7 +43,7 @@ #include #include "src/core/lib/debug/stats.h" -#include "src/core/lib/gpr++/manual_constructor.h" +#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/block_annotate.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" diff --git a/src/core/lib/surface/lame_client.cc b/src/core/lib/surface/lame_client.cc index 27a2a4eeb6..a1f1cf1107 100644 --- a/src/core/lib/surface/lame_client.cc +++ b/src/core/lib/surface/lame_client.cc @@ -23,7 +23,7 @@ #include #include -#include "src/core/lib/gpr++/atomic.h" +#include "src/core/lib/gprpp/atomic.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/gpr/string.h" -- cgit v1.2.3