added iOS source code
[wl-app.git] / iOS / Pods / Realm / Realm / ObjectStore / src / thread_safe_reference.cpp
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2016 Realm Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 ////////////////////////////////////////////////////////////////////////////
18
19 #include "thread_safe_reference.hpp"
20
21 #include "impl/realm_coordinator.hpp"
22 #include "list.hpp"
23 #include "object.hpp"
24 #include "object_schema.hpp"
25 #include "results.hpp"
26
27 #include <realm/util/scope_exit.hpp>
28
29 using namespace realm;
30
31 ThreadSafeReferenceBase::ThreadSafeReferenceBase(SharedRealm source_realm) : m_source_realm(std::move(source_realm))
32 {
33     m_source_realm->verify_thread();
34     if (m_source_realm->is_in_transaction()) {
35         throw InvalidTransactionException("Cannot obtain thread safe reference during a write transaction.");
36     }
37
38     try {
39         m_version_id = get_source_shared_group().pin_version();
40     } catch (...) {
41         invalidate();
42         throw;
43     }
44 }
45
46 ThreadSafeReferenceBase::~ThreadSafeReferenceBase()
47 {
48     if (!is_invalidated())
49         invalidate();
50 }
51
52 template <typename V, typename T>
53 V ThreadSafeReferenceBase::invalidate_after_import(Realm& destination_realm, T construct_with_shared_group) {
54     destination_realm.verify_thread();
55     REALM_ASSERT_DEBUG(!m_source_realm->is_in_transaction());
56     REALM_ASSERT_DEBUG(!is_invalidated());
57
58     SharedGroup& destination_shared_group = *Realm::Internal::get_shared_group(destination_realm);
59     auto unpin_version = util::make_scope_exit([&]() noexcept { invalidate(); });
60
61     return construct_with_shared_group(destination_shared_group);
62 }
63
64 SharedGroup& ThreadSafeReferenceBase::get_source_shared_group() const {
65     return *Realm::Internal::get_shared_group(*m_source_realm);
66 }
67
68 bool ThreadSafeReferenceBase::has_same_config(Realm& realm) const {
69     return &Realm::Internal::get_coordinator(*m_source_realm) == &Realm::Internal::get_coordinator(realm);
70 }
71
72 void ThreadSafeReferenceBase::invalidate() {
73     REALM_ASSERT_DEBUG(m_source_realm);
74     SharedRealm thread_local_realm = Realm::Internal::get_coordinator(*m_source_realm).get_realm();
75     Realm::Internal::get_shared_group(*thread_local_realm)->unpin_version(m_version_id);
76     m_source_realm = nullptr;
77 }
78
79 ThreadSafeReference<List>::ThreadSafeReference(List const& list)
80 : ThreadSafeReferenceBase(list.get_realm())
81 , m_link_view(get_source_shared_group().export_linkview_for_handover(list.m_link_view))
82 , m_table(get_source_shared_group().export_table_for_handover(list.m_table))
83 { }
84
85 List ThreadSafeReference<List>::import_into_realm(SharedRealm realm) && {
86     return invalidate_after_import<List>(*realm, [&](SharedGroup& shared_group) {
87         if (auto link_view = shared_group.import_linkview_from_handover(std::move(m_link_view)))
88             return List(std::move(realm), std::move(link_view));
89         return List(std::move(realm), shared_group.import_table_from_handover(std::move(m_table)));
90     });
91 }
92
93 ThreadSafeReference<Object>::ThreadSafeReference(Object const& object)
94 : ThreadSafeReferenceBase(object.realm())
95 , m_row(get_source_shared_group().export_for_handover(Row(object.row())))
96 , m_object_schema_name(object.get_object_schema().name) { }
97
98 Object ThreadSafeReference<Object>::import_into_realm(SharedRealm realm) && {
99     return invalidate_after_import<Object>(*realm, [&](SharedGroup& shared_group) {
100         Row row = *shared_group.import_from_handover(std::move(m_row));
101         auto object_schema = realm->schema().find(m_object_schema_name);
102         REALM_ASSERT_DEBUG(object_schema != realm->schema().end());
103         return Object(std::move(realm), *object_schema, row);
104     });
105 }
106
107 ThreadSafeReference<Results>::ThreadSafeReference(Results const& results)
108 : ThreadSafeReferenceBase(results.get_realm())
109 , m_query(get_source_shared_group().export_for_handover(results.get_query(), ConstSourcePayload::Copy))
110 , m_ordering_patch([&]() {
111     DescriptorOrdering::HandoverPatch ordering_patch;
112     DescriptorOrdering::generate_patch(results.get_descriptor_ordering(), ordering_patch);
113     return ordering_patch;
114 }()){ }
115
116 Results ThreadSafeReference<Results>::import_into_realm(SharedRealm realm) && {
117     return invalidate_after_import<Results>(*realm, [&](SharedGroup& shared_group) {
118         Query query = *shared_group.import_from_handover(std::move(m_query));
119         Table& table = *query.get_table();
120         DescriptorOrdering descriptors = DescriptorOrdering::create_from_and_consume_patch(m_ordering_patch, table);
121         return Results(std::move(realm), std::move(query), std::move(descriptors));
122     });
123 }