11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef INCLUDE_CPPGC_PREFINALIZER_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_PREFINALIZER_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "cppgc/internal/compiler-specific.h"
91cb0ef41Sopenharmony_ci#include "cppgc/liveness-broker.h"
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_cinamespace cppgc {
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace internal {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciclass V8_EXPORT PrefinalizerRegistration final {
161cb0ef41Sopenharmony_ci public:
171cb0ef41Sopenharmony_ci  using Callback = bool (*)(const cppgc::LivenessBroker&, void*);
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci  PrefinalizerRegistration(void*, Callback);
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  void* operator new(size_t, void* location) = delete;
221cb0ef41Sopenharmony_ci  void* operator new(size_t) = delete;
231cb0ef41Sopenharmony_ci};
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci}  // namespace internal
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci/**
281cb0ef41Sopenharmony_ci * Macro must be used in the private section of `Class` and registers a
291cb0ef41Sopenharmony_ci * prefinalization callback `void Class::PreFinalizer()`. The callback is
301cb0ef41Sopenharmony_ci * invoked on garbage collection after the collector has found an object to be
311cb0ef41Sopenharmony_ci * dead.
321cb0ef41Sopenharmony_ci *
331cb0ef41Sopenharmony_ci * Callback properties:
341cb0ef41Sopenharmony_ci * - The callback is invoked before a possible destructor for the corresponding
351cb0ef41Sopenharmony_ci *   object.
361cb0ef41Sopenharmony_ci * - The callback may access the whole object graph, irrespective of whether
371cb0ef41Sopenharmony_ci *   objects are considered dead or alive.
381cb0ef41Sopenharmony_ci * - The callback is invoked on the same thread as the object was created on.
391cb0ef41Sopenharmony_ci *
401cb0ef41Sopenharmony_ci * Example:
411cb0ef41Sopenharmony_ci * \code
421cb0ef41Sopenharmony_ci * class WithPrefinalizer : public GarbageCollected<WithPrefinalizer> {
431cb0ef41Sopenharmony_ci *   CPPGC_USING_PRE_FINALIZER(WithPrefinalizer, Dispose);
441cb0ef41Sopenharmony_ci *
451cb0ef41Sopenharmony_ci *  public:
461cb0ef41Sopenharmony_ci *   void Trace(Visitor*) const {}
471cb0ef41Sopenharmony_ci *   void Dispose() { prefinalizer_called = true; }
481cb0ef41Sopenharmony_ci *   ~WithPrefinalizer() {
491cb0ef41Sopenharmony_ci *     // prefinalizer_called == true
501cb0ef41Sopenharmony_ci *   }
511cb0ef41Sopenharmony_ci *  private:
521cb0ef41Sopenharmony_ci *   bool prefinalizer_called = false;
531cb0ef41Sopenharmony_ci * };
541cb0ef41Sopenharmony_ci * \endcode
551cb0ef41Sopenharmony_ci */
561cb0ef41Sopenharmony_ci#define CPPGC_USING_PRE_FINALIZER(Class, PreFinalizer)                         \
571cb0ef41Sopenharmony_ci public:                                                                       \
581cb0ef41Sopenharmony_ci  static bool InvokePreFinalizer(const cppgc::LivenessBroker& liveness_broker, \
591cb0ef41Sopenharmony_ci                                 void* object) {                               \
601cb0ef41Sopenharmony_ci    static_assert(cppgc::IsGarbageCollectedOrMixinTypeV<Class>,                \
611cb0ef41Sopenharmony_ci                  "Only garbage collected objects can have prefinalizers");    \
621cb0ef41Sopenharmony_ci    Class* self = static_cast<Class*>(object);                                 \
631cb0ef41Sopenharmony_ci    if (liveness_broker.IsHeapObjectAlive(self)) return false;                 \
641cb0ef41Sopenharmony_ci    self->PreFinalizer();                                                      \
651cb0ef41Sopenharmony_ci    return true;                                                               \
661cb0ef41Sopenharmony_ci  }                                                                            \
671cb0ef41Sopenharmony_ci                                                                               \
681cb0ef41Sopenharmony_ci private:                                                                      \
691cb0ef41Sopenharmony_ci  CPPGC_NO_UNIQUE_ADDRESS cppgc::internal::PrefinalizerRegistration            \
701cb0ef41Sopenharmony_ci      prefinalizer_dummy_{this, Class::InvokePreFinalizer};                    \
711cb0ef41Sopenharmony_ci  static_assert(true, "Force semicolon.")
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci}  // namespace cppgc
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci#endif  // INCLUDE_CPPGC_PREFINALIZER_H_
76