2 * Copyright 2014-present Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <folly/io/async/DelayedDestructionBase.h>
21 #include <glog/logging.h>
26 * DelayedDestruction is a helper class to ensure objects are not deleted
27 * while they still have functions executing in a higher stack frame.
29 * This is useful for objects that invoke callback functions, to ensure that a
30 * callback does not destroy the calling object.
32 * Classes needing this functionality should:
33 * - derive from DelayedDestruction
34 * - make their destructor private or protected, so it cannot be called
36 * - create a DestructorGuard object on the stack in each public method that
37 * may invoke a callback
39 * DelayedDestruction does not perform any locking. It is intended to be used
40 * only from a single thread.
42 class DelayedDestruction : public DelayedDestructionBase {
45 * destroy() requests destruction of the object.
47 * This method will destroy the object after it has no more functions running
48 * higher up on the stack. (i.e., No more DestructorGuard objects exist for
49 * this object.) This method must be used instead of the destructor.
51 virtual void destroy() {
52 // If guardCount_ is not 0, just set destroyPending_ to delay
53 // actual destruction.
54 if (getDestructorGuardCount() != 0) {
55 destroyPending_ = true;
57 onDelayedDestroy(false);
62 * Helper class to allow DelayedDestruction classes to be used with
65 * This class can be specified as the destructor argument when creating the
66 * shared_ptr, and it will destroy the guarded class properly when all
67 * shared_ptr references are released.
71 void operator()(DelayedDestruction* dd) const {
76 bool getDestroyPending() const {
77 return destroyPending_;
82 * Protected destructor.
84 * Making this protected ensures that users cannot delete DelayedDestruction
85 * objects directly, and that everyone must use destroy() instead.
86 * Subclasses of DelayedDestruction must also define their destructors as
87 * protected or private in order for this to work.
89 * This also means that DelayedDestruction objects cannot be created
90 * directly on the stack; they must always be dynamically allocated on the
93 * In order to use a DelayedDestruction object with a shared_ptr, create the
94 * shared_ptr using a DelayedDestruction::Destructor as the second argument
95 * to the shared_ptr constructor.
97 ~DelayedDestruction() override = default;
100 : destroyPending_(false) {
105 * destroyPending_ is set to true if destoy() is called while guardCount_ is
106 * non-zero. It is set to false before the object is deleted.
108 * If destroyPending_ is true, the object will be destroyed the next time
109 * guardCount_ drops to 0.
111 bool destroyPending_;
113 void onDelayedDestroy(bool delayed) override {
114 // check if it is ok to destroy now
115 if (delayed && !destroyPending_) {
118 destroyPending_ = false;