added iOS source code
[wl-app.git] / iOS / Pods / Realm / Realm / ObjectStore / src / thread_safe_reference.cpp
diff --git a/iOS/Pods/Realm/Realm/ObjectStore/src/thread_safe_reference.cpp b/iOS/Pods/Realm/Realm/ObjectStore/src/thread_safe_reference.cpp
new file mode 100644 (file)
index 0000000..9469d89
--- /dev/null
@@ -0,0 +1,123 @@
+////////////////////////////////////////////////////////////////////////////
+//
+// 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 "thread_safe_reference.hpp"
+
+#include "impl/realm_coordinator.hpp"
+#include "list.hpp"
+#include "object.hpp"
+#include "object_schema.hpp"
+#include "results.hpp"
+
+#include <realm/util/scope_exit.hpp>
+
+using namespace realm;
+
+ThreadSafeReferenceBase::ThreadSafeReferenceBase(SharedRealm source_realm) : m_source_realm(std::move(source_realm))
+{
+    m_source_realm->verify_thread();
+    if (m_source_realm->is_in_transaction()) {
+        throw InvalidTransactionException("Cannot obtain thread safe reference during a write transaction.");
+    }
+
+    try {
+        m_version_id = get_source_shared_group().pin_version();
+    } catch (...) {
+        invalidate();
+        throw;
+    }
+}
+
+ThreadSafeReferenceBase::~ThreadSafeReferenceBase()
+{
+    if (!is_invalidated())
+        invalidate();
+}
+
+template <typename V, typename T>
+V ThreadSafeReferenceBase::invalidate_after_import(Realm& destination_realm, T construct_with_shared_group) {
+    destination_realm.verify_thread();
+    REALM_ASSERT_DEBUG(!m_source_realm->is_in_transaction());
+    REALM_ASSERT_DEBUG(!is_invalidated());
+
+    SharedGroup& destination_shared_group = *Realm::Internal::get_shared_group(destination_realm);
+    auto unpin_version = util::make_scope_exit([&]() noexcept { invalidate(); });
+
+    return construct_with_shared_group(destination_shared_group);
+}
+
+SharedGroup& ThreadSafeReferenceBase::get_source_shared_group() const {
+    return *Realm::Internal::get_shared_group(*m_source_realm);
+}
+
+bool ThreadSafeReferenceBase::has_same_config(Realm& realm) const {
+    return &Realm::Internal::get_coordinator(*m_source_realm) == &Realm::Internal::get_coordinator(realm);
+}
+
+void ThreadSafeReferenceBase::invalidate() {
+    REALM_ASSERT_DEBUG(m_source_realm);
+    SharedRealm thread_local_realm = Realm::Internal::get_coordinator(*m_source_realm).get_realm();
+    Realm::Internal::get_shared_group(*thread_local_realm)->unpin_version(m_version_id);
+    m_source_realm = nullptr;
+}
+
+ThreadSafeReference<List>::ThreadSafeReference(List const& list)
+: ThreadSafeReferenceBase(list.get_realm())
+, m_link_view(get_source_shared_group().export_linkview_for_handover(list.m_link_view))
+, m_table(get_source_shared_group().export_table_for_handover(list.m_table))
+{ }
+
+List ThreadSafeReference<List>::import_into_realm(SharedRealm realm) && {
+    return invalidate_after_import<List>(*realm, [&](SharedGroup& shared_group) {
+        if (auto link_view = shared_group.import_linkview_from_handover(std::move(m_link_view)))
+            return List(std::move(realm), std::move(link_view));
+        return List(std::move(realm), shared_group.import_table_from_handover(std::move(m_table)));
+    });
+}
+
+ThreadSafeReference<Object>::ThreadSafeReference(Object const& object)
+: ThreadSafeReferenceBase(object.realm())
+, m_row(get_source_shared_group().export_for_handover(Row(object.row())))
+, m_object_schema_name(object.get_object_schema().name) { }
+
+Object ThreadSafeReference<Object>::import_into_realm(SharedRealm realm) && {
+    return invalidate_after_import<Object>(*realm, [&](SharedGroup& shared_group) {
+        Row row = *shared_group.import_from_handover(std::move(m_row));
+        auto object_schema = realm->schema().find(m_object_schema_name);
+        REALM_ASSERT_DEBUG(object_schema != realm->schema().end());
+        return Object(std::move(realm), *object_schema, row);
+    });
+}
+
+ThreadSafeReference<Results>::ThreadSafeReference(Results const& results)
+: ThreadSafeReferenceBase(results.get_realm())
+, m_query(get_source_shared_group().export_for_handover(results.get_query(), ConstSourcePayload::Copy))
+, m_ordering_patch([&]() {
+    DescriptorOrdering::HandoverPatch ordering_patch;
+    DescriptorOrdering::generate_patch(results.get_descriptor_ordering(), ordering_patch);
+    return ordering_patch;
+}()){ }
+
+Results ThreadSafeReference<Results>::import_into_realm(SharedRealm realm) && {
+    return invalidate_after_import<Results>(*realm, [&](SharedGroup& shared_group) {
+        Query query = *shared_group.import_from_handover(std::move(m_query));
+        Table& table = *query.get_table();
+        DescriptorOrdering descriptors = DescriptorOrdering::create_from_and_consume_patch(m_ordering_patch, table);
+        return Results(std::move(realm), std::move(query), std::move(descriptors));
+    });
+}