2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
22 #include <type_traits>
29 * A helper class to allow a DelayedDestruction object to be instantiated on
32 * This class derives from an existing DelayedDestruction type and makes the
33 * destructor public again. This allows objects of this type to be declared on
34 * the stack or directly inside another class. Normally DelayedDestruction
35 * objects must be dynamically allocated on the heap.
37 * However, the trade-off is that you lose some of the protections provided by
38 * DelayedDestruction::destroy(). DelayedDestruction::destroy() will
39 * automatically delay destruction of the object until it is safe to do so.
40 * If you use UndelayedDestruction, you become responsible for ensuring that
41 * you only destroy the object where it is safe to do so. Attempting to
42 * destroy a UndelayedDestruction object while it has a non-zero destructor
43 * guard count will abort the program.
45 template<typename TDD>
46 class UndelayedDestruction : public TDD {
48 // We could just use constructor inheritance, but not all compilers
49 // support that. So, just use a forwarding constructor.
51 // Ideally we would use std::enable_if<> and std::is_constructible<> to
52 // provide only constructor methods that are valid for our parent class.
53 // Unfortunately std::is_constructible<> doesn't work for types that aren't
54 // destructible. In gcc-4.6 it results in a compiler error. In the latest
55 // gcc code it looks like it has been fixed to return false. (The language
56 // in the standard seems to indicate that returning false is the correct
57 // behavior for non-destructible types, which is unfortunate.)
58 template<typename ...Args>
59 explicit UndelayedDestruction(Args&& ...args)
60 : TDD(std::forward<Args>(args)...) {
61 this->TDD::onDestroy_ = [&, this] (bool delayed) {
62 if (delayed && !this->TDD::getDestroyPending()) {
65 // Do nothing. This will always be invoked from the call to destroy
66 // inside our destructor.
68 // prevent unused variable warnings when asserts are compiled out.
76 * The caller is responsible for ensuring that the object is only destroyed
77 * where it is safe to do so. (i.e., when the destructor guard count is 0).
79 * The exact conditions for meeting this may be dependant upon your class
80 * semantics. Typically you are only guaranteed that it is safe to destroy
81 * the object directly from the event loop (e.g., directly from a
82 * EventBase::LoopCallback), or when the event loop is stopped.
84 virtual ~UndelayedDestruction() {
85 // Crash if the caller is destroying us with outstanding destructor guards.
86 if (this->getDestructorGuardCount() != 0) {
89 // Invoke destroy. This is necessary since our base class may have
90 // implemented custom behavior in destroy().
96 * Override our parent's destroy() method to make it protected.
97 * Callers should use the normal destructor instead of destroy
99 virtual void destroy() {
100 this->TDD::destroy();
104 // Forbidden copy constructor and assignment operator
105 UndelayedDestruction(UndelayedDestruction const &) = delete;
106 UndelayedDestruction& operator=(UndelayedDestruction const &) = delete;