added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / util / apple / event_loop_signal.hpp
diff --git a/iOS/Pods/Realm/include/util/apple/event_loop_signal.hpp b/iOS/Pods/Realm/include/util/apple/event_loop_signal.hpp
new file mode 100644 (file)
index 0000000..37a3d36
--- /dev/null
@@ -0,0 +1,82 @@
+////////////////////////////////////////////////////////////////////////////
+//
+// Copyright 2016 Realm Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////
+
+#include <atomic>
+#include <CoreFoundation/CFRunLoop.h>
+
+namespace realm {
+namespace util {
+template<typename Callback>
+class EventLoopSignal {
+public:
+    EventLoopSignal(Callback&& callback)
+    {
+        struct RefCountedRunloopCallback {
+            Callback callback;
+            std::atomic<size_t> ref_count;
+        };
+
+        CFRunLoopSourceContext ctx{};
+        ctx.info = new RefCountedRunloopCallback{std::move(callback), {0}};
+        ctx.perform = [](void* info) {
+            static_cast<RefCountedRunloopCallback*>(info)->callback();
+        };
+        ctx.retain = [](const void* info) {
+            static_cast<RefCountedRunloopCallback*>(const_cast<void*>(info))->ref_count.fetch_add(1, std::memory_order_relaxed);
+            return info;
+        };
+        ctx.release = [](const void* info) {
+            auto ptr = static_cast<RefCountedRunloopCallback*>(const_cast<void*>(info));
+            if (ptr->ref_count.fetch_add(-1, std::memory_order_acq_rel) == 1) {
+                delete ptr;
+            }
+        };
+
+        m_runloop = CFRunLoopGetCurrent();
+        CFRetain(m_runloop);
+        m_signal = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &ctx);
+        CFRunLoopAddSource(m_runloop, m_signal, kCFRunLoopDefaultMode);
+    }
+
+    ~EventLoopSignal()
+    {
+        CFRunLoopSourceInvalidate(m_signal);
+        CFRelease(m_signal);
+        CFRelease(m_runloop);
+    }
+
+    EventLoopSignal(EventLoopSignal&&) = delete;
+    EventLoopSignal& operator=(EventLoopSignal&&) = delete;
+    EventLoopSignal(EventLoopSignal const&) = delete;
+    EventLoopSignal& operator=(EventLoopSignal const&) = delete;
+
+    void notify()
+    {
+        CFRunLoopSourceSignal(m_signal);
+        // Signalling the source makes it run the next time the runloop gets
+        // to it, but doesn't make the runloop start if it's currently idle
+        // waiting for events
+        CFRunLoopWakeUp(m_runloop);
+    }
+
+private:
+    CFRunLoopRef m_runloop;
+    CFRunLoopSourceRef m_signal;
+};
+} // namespace util
+} // namespace realm