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_INTERNAL_FINALIZER_TRAIT_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_INTERNAL_FINALIZER_TRAIT_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <type_traits>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "cppgc/type-traits.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace cppgc {
131cb0ef41Sopenharmony_cinamespace internal {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciusing FinalizationCallback = void (*)(void*);
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_citemplate <typename T, typename = void>
181cb0ef41Sopenharmony_cistruct HasFinalizeGarbageCollectedObject : std::false_type {};
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_citemplate <typename T>
211cb0ef41Sopenharmony_cistruct HasFinalizeGarbageCollectedObject<
221cb0ef41Sopenharmony_ci    T,
231cb0ef41Sopenharmony_ci    std::void_t<decltype(std::declval<T>().FinalizeGarbageCollectedObject())>>
241cb0ef41Sopenharmony_ci    : std::true_type {};
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci// The FinalizerTraitImpl specifies how to finalize objects.
271cb0ef41Sopenharmony_citemplate <typename T, bool isFinalized>
281cb0ef41Sopenharmony_cistruct FinalizerTraitImpl;
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_citemplate <typename T>
311cb0ef41Sopenharmony_cistruct FinalizerTraitImpl<T, true> {
321cb0ef41Sopenharmony_ci private:
331cb0ef41Sopenharmony_ci  // Dispatch to custom FinalizeGarbageCollectedObject().
341cb0ef41Sopenharmony_ci  struct Custom {
351cb0ef41Sopenharmony_ci    static void Call(void* obj) {
361cb0ef41Sopenharmony_ci      static_cast<T*>(obj)->FinalizeGarbageCollectedObject();
371cb0ef41Sopenharmony_ci    }
381cb0ef41Sopenharmony_ci  };
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  // Dispatch to regular destructor.
411cb0ef41Sopenharmony_ci  struct Destructor {
421cb0ef41Sopenharmony_ci    static void Call(void* obj) { static_cast<T*>(obj)->~T(); }
431cb0ef41Sopenharmony_ci  };
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  using FinalizeImpl =
461cb0ef41Sopenharmony_ci      std::conditional_t<HasFinalizeGarbageCollectedObject<T>::value, Custom,
471cb0ef41Sopenharmony_ci                         Destructor>;
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci public:
501cb0ef41Sopenharmony_ci  static void Finalize(void* obj) {
511cb0ef41Sopenharmony_ci    static_assert(sizeof(T), "T must be fully defined");
521cb0ef41Sopenharmony_ci    FinalizeImpl::Call(obj);
531cb0ef41Sopenharmony_ci  }
541cb0ef41Sopenharmony_ci};
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_citemplate <typename T>
571cb0ef41Sopenharmony_cistruct FinalizerTraitImpl<T, false> {
581cb0ef41Sopenharmony_ci  static void Finalize(void* obj) {
591cb0ef41Sopenharmony_ci    static_assert(sizeof(T), "T must be fully defined");
601cb0ef41Sopenharmony_ci  }
611cb0ef41Sopenharmony_ci};
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci// The FinalizerTrait is used to determine if a type requires finalization and
641cb0ef41Sopenharmony_ci// what finalization means.
651cb0ef41Sopenharmony_citemplate <typename T>
661cb0ef41Sopenharmony_cistruct FinalizerTrait {
671cb0ef41Sopenharmony_ci private:
681cb0ef41Sopenharmony_ci  // Object has a finalizer if it has
691cb0ef41Sopenharmony_ci  // - a custom FinalizeGarbageCollectedObject method, or
701cb0ef41Sopenharmony_ci  // - a destructor.
711cb0ef41Sopenharmony_ci  static constexpr bool kNonTrivialFinalizer =
721cb0ef41Sopenharmony_ci      internal::HasFinalizeGarbageCollectedObject<T>::value ||
731cb0ef41Sopenharmony_ci      !std::is_trivially_destructible<typename std::remove_cv<T>::type>::value;
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  static void Finalize(void* obj) {
761cb0ef41Sopenharmony_ci    internal::FinalizerTraitImpl<T, kNonTrivialFinalizer>::Finalize(obj);
771cb0ef41Sopenharmony_ci  }
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci public:
801cb0ef41Sopenharmony_ci  static constexpr bool HasFinalizer() { return kNonTrivialFinalizer; }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  // The callback used to finalize an object of type T.
831cb0ef41Sopenharmony_ci  static constexpr FinalizationCallback kCallback =
841cb0ef41Sopenharmony_ci      kNonTrivialFinalizer ? Finalize : nullptr;
851cb0ef41Sopenharmony_ci};
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_citemplate <typename T>
881cb0ef41Sopenharmony_ciconstexpr FinalizationCallback FinalizerTrait<T>::kCallback;
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci}  // namespace internal
911cb0ef41Sopenharmony_ci}  // namespace cppgc
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci#endif  // INCLUDE_CPPGC_INTERNAL_FINALIZER_TRAIT_H_
94