callback.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright 2019 The Chromium 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. #ifndef GPU_WEBGPU_CALLBACK_H_
  5. #define GPU_WEBGPU_CALLBACK_H_
  6. #include <memory>
  7. #include "base/callback.h"
  8. namespace gpu::webgpu {
  9. // WGPUCallback<Callback> is a heap-allocated version of
  10. // base::OnceCallback or base::RepeatingCallback.
  11. // It is allocated on the heap so that it can be reinterpret_cast to/from
  12. // void* and passed to WGPU C callbacks.
  13. //
  14. // Example:
  15. // WGPUOnceCallback<F>* callback =
  16. // BindWGPUOnceCallback(func, arg1);
  17. //
  18. // // |someWGPUFunction| expects callback function with arguments:
  19. // // Args... args, void* userdata.
  20. // // When it is called, it will forward to func(arg1, args...).
  21. // GetProcs().someWGPUFunction(
  22. // callback->UnboundCallback(), callback->AsUserdata());
  23. template <typename Callback>
  24. class WGPUCallbackBase;
  25. template <typename Callback>
  26. class WGPUOnceCallback;
  27. template <typename Callback>
  28. class WGPURepeatingCallback;
  29. template <template <typename> class BaseCallbackTemplate,
  30. typename R,
  31. typename... Args>
  32. class WGPUCallbackBase<BaseCallbackTemplate<R(Args...)>> {
  33. using BaseCallback = BaseCallbackTemplate<R(Args...)>;
  34. static constexpr bool is_once_callback =
  35. std::is_same<BaseCallback, base::OnceCallback<R(Args...)>>::value;
  36. static constexpr bool is_repeating_callback =
  37. std::is_same<BaseCallback, base::RepeatingCallback<R(Args...)>>::value;
  38. static_assert(
  39. is_once_callback || is_repeating_callback,
  40. "Callback must be base::OnceCallback or base::RepeatingCallback");
  41. public:
  42. explicit WGPUCallbackBase(BaseCallback callback)
  43. : callback_(std::move(callback)) {}
  44. void* AsUserdata() { return static_cast<void*>(this); }
  45. protected:
  46. using UnboundCallbackFunction = R (*)(Args..., void*);
  47. static WGPUCallbackBase* FromUserdata(void* userdata) {
  48. return static_cast<WGPUCallbackBase*>(userdata);
  49. }
  50. R Run(Args... args) && {
  51. static_assert(
  52. is_once_callback,
  53. "Run on a moved receiver must only be called on a once callback.");
  54. return std::move(callback_).Run(std::forward<Args>(args)...);
  55. }
  56. R Run(Args... args) const& {
  57. static_assert(is_repeating_callback,
  58. "Run on a unmoved receiver must only be called on a "
  59. "repeating callback.");
  60. return callback_.Run(std::forward<Args>(args)...);
  61. }
  62. private:
  63. BaseCallback callback_;
  64. };
  65. template <typename R, typename... Args>
  66. class WGPUOnceCallback<R(Args...)>
  67. : public WGPUCallbackBase<base::OnceCallback<R(Args...)>> {
  68. using BaseCallback = base::OnceCallback<R(Args...)>;
  69. public:
  70. using WGPUCallbackBase<BaseCallback>::WGPUCallbackBase;
  71. typename WGPUCallbackBase<BaseCallback>::UnboundCallbackFunction
  72. UnboundCallback() {
  73. return CallUnboundOnceCallback;
  74. }
  75. private:
  76. static R CallUnboundOnceCallback(Args... args, void* handle) {
  77. // After this non-repeating callback is run, it should delete itself.
  78. auto callback =
  79. std::unique_ptr<WGPUOnceCallback>(static_cast<WGPUOnceCallback*>(
  80. WGPUCallbackBase<BaseCallback>::FromUserdata(handle)));
  81. return std::move(*callback).Run(std::forward<Args>(args)...);
  82. }
  83. };
  84. template <typename R, typename... Args>
  85. class WGPURepeatingCallback<R(Args...)>
  86. : public WGPUCallbackBase<base::RepeatingCallback<R(Args...)>> {
  87. using BaseCallback = base::RepeatingCallback<R(Args...)>;
  88. public:
  89. using WGPUCallbackBase<BaseCallback>::WGPUCallbackBase;
  90. typename WGPUCallbackBase<BaseCallback>::UnboundCallbackFunction
  91. UnboundCallback() {
  92. return CallUnboundRepeatingCallback;
  93. }
  94. private:
  95. static R CallUnboundRepeatingCallback(Args... args, void* handle) {
  96. return static_cast<WGPURepeatingCallback*>(
  97. WGPUCallbackBase<BaseCallback>::FromUserdata(handle))
  98. ->Run(std::forward<Args>(args)...);
  99. }
  100. };
  101. template <typename FunctionType, typename... BoundParameters>
  102. auto BindWGPUOnceCallback(FunctionType&& function,
  103. BoundParameters&&... bound_parameters) {
  104. static constexpr bool is_method =
  105. base::internal::MakeFunctorTraits<FunctionType>::is_method;
  106. static constexpr bool is_weak_method =
  107. base::internal::IsWeakMethod<is_method, BoundParameters...>();
  108. static_assert(!is_weak_method,
  109. "BindWGPUOnceCallback cannot be used with weak methods");
  110. auto cb = base::BindOnce(std::forward<FunctionType>(function),
  111. std::forward<BoundParameters>(bound_parameters)...);
  112. return new WGPUOnceCallback<typename decltype(cb)::RunType>(std::move(cb));
  113. }
  114. template <typename FunctionType, typename... BoundParameters>
  115. auto BindWGPURepeatingCallback(FunctionType&& function,
  116. BoundParameters&&... bound_parameters) {
  117. auto cb =
  118. base::BindRepeating(std::forward<FunctionType>(function),
  119. std::forward<BoundParameters>(bound_parameters)...);
  120. return std::make_unique<
  121. WGPURepeatingCallback<typename decltype(cb)::RunType>>(std::move(cb));
  122. }
  123. } // namespace gpu::webgpu
  124. #endif // GPU_WEBGPU_CALLBACK_H_