Mark D. Roth | 70db663 | 2017-11-27 14:53:26 -0800 | [diff] [blame] | 1 | /* |
| 2 | * |
| 3 | * Copyright 2017 gRPC authors. |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | * |
| 17 | */ |
| 18 | |
| 19 | #ifndef GRPC_CORE_LIB_SUPPORT_REFERENCE_COUNTED_H |
| 20 | #define GRPC_CORE_LIB_SUPPORT_REFERENCE_COUNTED_H |
| 21 | |
| 22 | #include <grpc/support/sync.h> |
Mark D. Roth | b319f49 | 2017-11-28 14:50:07 -0800 | [diff] [blame^] | 23 | #include <grpc/support/log.h> |
Mark D. Roth | 70db663 | 2017-11-27 14:53:26 -0800 | [diff] [blame] | 24 | |
| 25 | #include "src/core/lib/debug/trace.h" |
| 26 | #include "src/core/lib/support/debug_location.h" |
Mark D. Roth | b319f49 | 2017-11-28 14:50:07 -0800 | [diff] [blame^] | 27 | #include "src/core/lib/support/memory.h" |
Mark D. Roth | 70db663 | 2017-11-27 14:53:26 -0800 | [diff] [blame] | 28 | |
| 29 | namespace grpc_core { |
| 30 | |
Mark D. Roth | b319f49 | 2017-11-28 14:50:07 -0800 | [diff] [blame^] | 31 | // A base class for reference-counted objects. |
| 32 | // New objects should be created via New() and start with a refcount of 1. |
| 33 | // When the refcount reaches 0, the object will be deleted via Delete(). |
Mark D. Roth | 70db663 | 2017-11-27 14:53:26 -0800 | [diff] [blame] | 34 | class ReferenceCounted { |
| 35 | public: |
Mark D. Roth | b319f49 | 2017-11-28 14:50:07 -0800 | [diff] [blame^] | 36 | void Ref() { gpr_ref(&refs_); } |
Mark D. Roth | 70db663 | 2017-11-27 14:53:26 -0800 | [diff] [blame] | 37 | |
Mark D. Roth | b319f49 | 2017-11-28 14:50:07 -0800 | [diff] [blame^] | 38 | void Ref(const DebugLocation& location, const char* reason) { |
| 39 | if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { |
| 40 | gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); |
| 41 | gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", |
| 42 | trace_flag_->name(), this, location.file(), location.line(), |
| 43 | old_refs, old_refs + 1, reason); |
| 44 | } |
| 45 | Ref(); |
| 46 | } |
| 47 | |
| 48 | void Unref() { |
| 49 | if (gpr_unref(&refs_)) { |
| 50 | Delete(this); |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | void Unref(const DebugLocation& location, const char* reason) { |
| 55 | if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { |
| 56 | gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); |
| 57 | gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", |
| 58 | trace_flag_->name(), this, location.file(), location.line(), |
| 59 | old_refs, old_refs - 1, reason); |
| 60 | } |
| 61 | Unref(); |
| 62 | } |
Mark D. Roth | 70db663 | 2017-11-27 14:53:26 -0800 | [diff] [blame] | 63 | |
| 64 | // Not copyable nor movable. |
| 65 | ReferenceCounted(const ReferenceCounted&) = delete; |
| 66 | ReferenceCounted& operator=(const ReferenceCounted&) = delete; |
| 67 | |
| 68 | protected: |
Mark D. Roth | abadc6c | 2017-11-28 08:24:10 -0800 | [diff] [blame] | 69 | // Allow Delete() to access destructor. |
Mark D. Roth | d3984c3 | 2017-11-28 09:13:27 -0800 | [diff] [blame] | 70 | template <typename T> |
Mark D. Roth | abadc6c | 2017-11-28 08:24:10 -0800 | [diff] [blame] | 71 | friend void Delete(T*); |
| 72 | |
Mark D. Roth | b319f49 | 2017-11-28 14:50:07 -0800 | [diff] [blame^] | 73 | ReferenceCounted() : ReferenceCounted(nullptr) {} |
| 74 | |
Mark D. Roth | 70db663 | 2017-11-27 14:53:26 -0800 | [diff] [blame] | 75 | explicit ReferenceCounted(TraceFlag* trace_flag) : trace_flag_(trace_flag) { |
| 76 | gpr_ref_init(&refs_, 1); |
| 77 | } |
| 78 | |
| 79 | virtual ~ReferenceCounted() {} |
| 80 | |
| 81 | private: |
Mark D. Roth | b319f49 | 2017-11-28 14:50:07 -0800 | [diff] [blame^] | 82 | TraceFlag* trace_flag_ = nullptr; |
Mark D. Roth | 70db663 | 2017-11-27 14:53:26 -0800 | [diff] [blame] | 83 | gpr_refcount refs_; |
| 84 | }; |
| 85 | |
| 86 | } // namespace grpc_core |
| 87 | |
Mark D. Roth | 3228489 | 2017-11-28 09:12:16 -0800 | [diff] [blame] | 88 | #endif /* GRPC_CORE_LIB_SUPPORT_REFERENCE_COUNTED_H */ |