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
11namespace cppgc {
12
13namespace internal {
14
15class 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