1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef INCLUDE_CPPGC_PREFINALIZER_H_
6 #define INCLUDE_CPPGC_PREFINALIZER_H_
7 
8 #include "cppgc/internal/compiler-specific.h"
9 #include "cppgc/liveness-broker.h"
10 
11 namespace cppgc {
12 
13 namespace internal {
14 
15 class V8_EXPORT PrefinalizerRegistration final {
16  public:
17   using Callback = bool (*)(const cppgc::LivenessBroker&, void*);
18 
19   PrefinalizerRegistration(void*, Callback);
20 
21   void* operator new(size_t, void* location) = delete;
22   void* operator new(size_t) = delete;
23 };
24 
25 }  // namespace internal
26 
27 /**
28  * Macro must be used in the private section of `Class` and registers a
29  * prefinalization callback `void Class::PreFinalizer()`. The callback is
30  * invoked on garbage collection after the collector has found an object to be
31  * dead.
32  *
33  * Callback properties:
34  * - The callback is invoked before a possible destructor for the corresponding
35  *   object.
36  * - The callback may access the whole object graph, irrespective of whether
37  *   objects are considered dead or alive.
38  * - The callback is invoked on the same thread as the object was created on.
39  *
40  * Example:
41  * \code
42  * class WithPrefinalizer : public GarbageCollected<WithPrefinalizer> {
43  *   CPPGC_USING_PRE_FINALIZER(WithPrefinalizer, Dispose);
44  *
45  *  public:
46  *   void Trace(Visitor*) const {}
47  *   void Dispose() { prefinalizer_called = true; }
48  *   ~WithPrefinalizer() {
49  *     // prefinalizer_called == true
50  *   }
51  *  private:
52  *   bool prefinalizer_called = false;
53  * };
54  * \endcode
55  */
56 #define CPPGC_USING_PRE_FINALIZER(Class, PreFinalizer)                         \
57  public:                                                                       \
58   static bool InvokePreFinalizer(const cppgc::LivenessBroker& liveness_broker, \
59                                  void* object) {                               \
60     static_assert(cppgc::IsGarbageCollectedOrMixinTypeV<Class>,                \
61                   "Only garbage collected objects can have prefinalizers");    \
62     Class* self = static_cast<Class*>(object);                                 \
63     if (liveness_broker.IsHeapObjectAlive(self)) return false;                 \
64     self->PreFinalizer();                                                      \
65     return true;                                                               \
66   }                                                                            \
67                                                                                \
68  private:                                                                      \
69   CPPGC_NO_UNIQUE_ADDRESS cppgc::internal::PrefinalizerRegistration            \
70       prefinalizer_dummy_{this, Class::InvokePreFinalizer};                    \
71   static_assert(true, "Force semicolon.")
72 
73 }  // namespace cppgc
74 
75 #endif  // INCLUDE_CPPGC_PREFINALIZER_H_
76