Commit 6a497f5c authored by Andrew Twyman's avatar Andrew Twyman Committed by GitHub

Merge pull request #292 from dropbox/atwyman/objc_proxy_cleanup

Simplify ObjcProxyBase
parents 7e09a2c2 bbf14ae0
...@@ -55,15 +55,23 @@ static std::shared_ptr<CppType> get_objc_proxy(ObjcType * objcRef) { ...@@ -55,15 +55,23 @@ static std::shared_ptr<CppType> get_objc_proxy(ObjcType * objcRef) {
// Private implementation base class for all ObjC proxies, which manages the // Private implementation base class for all ObjC proxies, which manages the
// Handle, and ensures that it is created and destroyed in a safe way, inside // Handle, and ensures that it is created and destroyed in a safe way, inside
// of an @autoreleasepool to avoid leaks. Most of the complexity here is just // of an @autoreleasepool to avoid leaks. The complexity here is just necessary
// necessary to gain explicit control of construction and destruction time of // to gain explicit control of construction and destruction time of the member
// the member Handle, to make sure it's inside the @autoreleasepool block. // Handle, to make sure it's inside the @autoreleasepool block.
// An optional<HandleType> would meet our needs, but we can't use it directly
// since the support-lib doesn't know which optional implementation might be in
// use, if any. We can't take OptionalType as a template arg here, because we
// also need to know where to find nullopt in order to implement the destructor
// above. This class uses the same technique as at least one optional
// implementation: The union ensures proper alignment, while leaving construction
// and destruction under our direct control.
template <typename ObjcType> template <typename ObjcType>
class ObjcProxyBase { class ObjcProxyBase {
using HandleType = ::djinni::ObjcProxyCache::Handle<ObjcType>;
public: public:
ObjcProxyBase(ObjcType objc) { ObjcProxyBase(ObjcType objc) {
@autoreleasepool { @autoreleasepool {
m_djinni_private_proxy_handle.emplace(objc); new (&m_djinni_private_proxy_handle) HandleType(objc);
} }
} }
...@@ -73,52 +81,23 @@ public: ...@@ -73,52 +81,23 @@ public:
// Not intended for polymorphic use, so dtor is not virtual // Not intended for polymorphic use, so dtor is not virtual
~ObjcProxyBase() { ~ObjcProxyBase() {
@autoreleasepool { @autoreleasepool {
m_djinni_private_proxy_handle.reset(); m_djinni_private_proxy_handle.~HandleType();
} }
} }
// Long name to minimize likelyhood of collision with interface methods. // Long name to minimize likelyhood of collision with interface methods.
ObjcType djinni_private_get_proxied_objc_object() const { // Return by reference to make it clear there's nothing for ARC to do here.
return m_djinni_private_proxy_handle.value().get(); // Call site should have its own autoreleasepool if necessary.
const ObjcType & djinni_private_get_proxied_objc_object() const {
return m_djinni_private_proxy_handle.get();
} }
private: private:
// Simple stand-in for std::experimental::optional since the union {
// support-lib doesn't know which optional implementation might be in use. // Long names to minimize likelyhood of collision with interface methods.
// We can't take OptionalType as a template arg here, because there's no char m_djinni_private_dummy;
// way to implement reset() without also knowing where to find nullopt, not HandleType m_djinni_private_proxy_handle;
// just optional itself. This class uses the same technique as at least
// one optional implementation: The union ensures proper alignment, while
// leaving construction and destruction under our direct control.
// This class is NOT safe for general use. It's safe only if emplace() and
// reset() are each called exactly once.
class OptionalObjcProxyHandle final {
public:
using HandleType = ::djinni::ObjcProxyCache::Handle<ObjcType>;
OptionalObjcProxyHandle() {};
OptionalObjcProxyHandle(const OptionalObjcProxyHandle&) = delete;
OptionalObjcProxyHandle& operator=(const OptionalObjcProxyHandle&) = delete;
~OptionalObjcProxyHandle() {};
void emplace(ObjcType objc) {
new (&m_handle) HandleType(objc);
}
void reset() {
m_handle.~HandleType();
}
const HandleType & value() const { return m_handle; }
private:
union {
char m_dummy;
HandleType m_handle;
};
}; };
// Long name to minimize likelyhood of collision with interface methods.
OptionalObjcProxyHandle m_djinni_private_proxy_handle;
}; };
} // namespace djinni } // namespace djinni
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment