DelayedDestruction.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  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
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  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.
  15. */
  16. #pragma once
  17. #include <folly/io/async/DelayedDestructionBase.h>
  18. #include <glog/logging.h>
  19. namespace folly {
  20. /**
  21. * DelayedDestruction is a helper class to ensure objects are not deleted
  22. * while they still have functions executing in a higher stack frame.
  23. *
  24. * This is useful for objects that invoke callback functions, to ensure that a
  25. * callback does not destroy the calling object.
  26. *
  27. * Classes needing this functionality should:
  28. * - derive from DelayedDestruction
  29. * - make their destructor private or protected, so it cannot be called
  30. * directly
  31. * - create a DestructorGuard object on the stack in each public method that
  32. * may invoke a callback
  33. *
  34. * DelayedDestruction does not perform any locking. It is intended to be used
  35. * only from a single thread.
  36. */
  37. class DelayedDestruction : public DelayedDestructionBase {
  38. public:
  39. /**
  40. * destroy() requests destruction of the object.
  41. *
  42. * This method will destroy the object after it has no more functions running
  43. * higher up on the stack. (i.e., No more DestructorGuard objects exist for
  44. * this object.) This method must be used instead of the destructor.
  45. */
  46. virtual void destroy() {
  47. // If guardCount_ is not 0, just set destroyPending_ to delay
  48. // actual destruction.
  49. if (getDestructorGuardCount() != 0) {
  50. destroyPending_ = true;
  51. } else {
  52. onDelayedDestroy(false);
  53. }
  54. }
  55. /**
  56. * Helper class to allow DelayedDestruction classes to be used with
  57. * std::shared_ptr.
  58. *
  59. * This class can be specified as the destructor argument when creating the
  60. * shared_ptr, and it will destroy the guarded class properly when all
  61. * shared_ptr references are released.
  62. */
  63. class Destructor {
  64. public:
  65. void operator()(DelayedDestruction* dd) const {
  66. dd->destroy();
  67. }
  68. };
  69. bool getDestroyPending() const {
  70. return destroyPending_;
  71. }
  72. protected:
  73. /**
  74. * Protected destructor.
  75. *
  76. * Making this protected ensures that users cannot delete DelayedDestruction
  77. * objects directly, and that everyone must use destroy() instead.
  78. * Subclasses of DelayedDestruction must also define their destructors as
  79. * protected or private in order for this to work.
  80. *
  81. * This also means that DelayedDestruction objects cannot be created
  82. * directly on the stack; they must always be dynamically allocated on the
  83. * heap.
  84. *
  85. * In order to use a DelayedDestruction object with a shared_ptr, create the
  86. * shared_ptr using a DelayedDestruction::Destructor as the second argument
  87. * to the shared_ptr constructor.
  88. */
  89. ~DelayedDestruction() override = default;
  90. DelayedDestruction() : destroyPending_(false) {}
  91. private:
  92. /**
  93. * destroyPending_ is set to true if destoy() is called while guardCount_ is
  94. * non-zero. It is set to false before the object is deleted.
  95. *
  96. * If destroyPending_ is true, the object will be destroyed the next time
  97. * guardCount_ drops to 0.
  98. */
  99. bool destroyPending_;
  100. void onDelayedDestroy(bool delayed) override {
  101. // check if it is ok to destroy now
  102. if (delayed && !destroyPending_) {
  103. return;
  104. }
  105. destroyPending_ = false;
  106. delete this;
  107. }
  108. };
  109. } // namespace folly