1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #pragma once
9 
10 #include <ABI48_0_0React/ABI48_0_0debug/ABI48_0_0React_native_assert.h>
11 
12 #if defined(__APPLE__)
13 #include <TargetConditionals.h>
14 #endif
15 
16 #if defined(__OBJC__) && defined(__cplusplus)
17 #if TARGET_OS_MAC
18 
19 #include <memory>
20 
21 #import <Foundation/Foundation.h>
22 
23 @interface ABI48_0_0RCTInternalGenericWeakWrapper : NSObject
property(nonatomic,weak)24 @property (nonatomic, weak) id object;
25 @end
26 
27 namespace ABI48_0_0facebook {
28 namespace ABI48_0_0React {
29 
30 namespace detail {
31 
32 /*
33  * A custom deleter used for the deallocation of Objective-C managed objects.
34  * To be used only by `wrapManagedObject`.
35  */
36 void wrappedManagedObjectDeleter(void *cfPointer) noexcept;
37 
38 }
39 
40 /*
41  * `wrapManagedObject` and `unwrapManagedObject` are wrapper functions that
42  * convert ARC-managed objects into `std::shared_ptr<void>` and vice-versa. It's
43  * a very useful mechanism when we need to pass Objective-C objects through pure
44  * C++ code, pass blocks into C++ lambdas, and so on.
45  *
46  * The idea behind this mechanism is quite simple but tricky: When we
47  * instantiate a C++ shared pointer for a managed object, we practically call
48  * `CFRetain` for it once and then we represent this single retaining operation
49  * as a counter inside the shared pointer; when the counter became zero, we call
50  * `CFRelease` on the object. In this model, one bump of ARC-managed counter is
51  * represented as multiple bumps of C++ counter, so we can have multiple
52  * counters for the same object that form some kind of counters tree.
53  */
54 inline std::shared_ptr<void> wrapManagedObject(id object) noexcept
55 {
56   return std::shared_ptr<void>((__bridge_retained void *)object, detail::wrappedManagedObjectDeleter);
57 }
58 
59 inline id unwrapManagedObject(std::shared_ptr<void> const &object) noexcept
60 {
61   return (__bridge id)object.get();
62 }
63 
64 inline std::shared_ptr<void> wrapManagedObjectWeakly(id object) noexcept
65 {
66   ABI48_0_0RCTInternalGenericWeakWrapper *weakWrapper = [ABI48_0_0RCTInternalGenericWeakWrapper new];
67   weakWrapper.object = object;
68   return wrapManagedObject(weakWrapper);
69 }
70 
71 inline id unwrapManagedObjectWeakly(std::shared_ptr<void> const &object) noexcept
72 {
73   ABI48_0_0RCTInternalGenericWeakWrapper *weakWrapper = (ABI48_0_0RCTInternalGenericWeakWrapper *)unwrapManagedObject(object);
74   ABI48_0_0React_native_assert(weakWrapper && "`ABI48_0_0RCTInternalGenericWeakWrapper` instance must not be `nil`.");
75   return weakWrapper.object;
76 }
77 
78 } // namespace ABI48_0_0React
79 } // namespace ABI48_0_0facebook
80 
81 #endif
82 #endif
83