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