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) {
// 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
// of an @autoreleasepool to avoid leaks. Most of the complexity here is just
// necessary to gain explicit control of construction and destruction time of
// the member Handle, to make sure it's inside the @autoreleasepool block.
// of an @autoreleasepool to avoid leaks. The complexity here is just necessary
// to gain explicit control of construction and destruction time of the member
// 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>
class ObjcProxyBase {
using HandleType = ::djinni::ObjcProxyCache::Handle<ObjcType>;
public:
ObjcProxyBase(ObjcType objc) {
@autoreleasepool {
m_djinni_private_proxy_handle.emplace(objc);
new (&m_djinni_private_proxy_handle) HandleType(objc);
}
}
......@@ -73,52 +81,23 @@ public:
// Not intended for polymorphic use, so dtor is not virtual
~ObjcProxyBase() {
@autoreleasepool {
m_djinni_private_proxy_handle.reset();
m_djinni_private_proxy_handle.~HandleType();
}
}
// Long name to minimize likelyhood of collision with interface methods.
ObjcType djinni_private_get_proxied_objc_object() const {
return m_djinni_private_proxy_handle.value().get();
// Return by reference to make it clear there's nothing for ARC to do here.
// 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:
// Simple stand-in for std::experimental::optional since the
// support-lib doesn't know which optional implementation might be in use.
// We can't take OptionalType as a template arg here, because there's no
// way to implement reset() without also knowing where to find nullopt, not
// 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;
};
union {
// Long names to minimize likelyhood of collision with interface methods.
char m_djinni_private_dummy;
HandleType m_djinni_private_proxy_handle;
};
// Long name to minimize likelyhood of collision with interface methods.
OptionalObjcProxyHandle m_djinni_private_proxy_handle;
};
} // 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