Coverage Report

Created: 2026-04-07 12:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
contrib/faiss/faiss/impl/maybe_owned_vector.h
Line
Count
Source
1
/*
2
 * Copyright (c) Meta Platforms, Inc. and affiliates.
3
 *
4
 * This source code is licensed under the MIT license found in the
5
 * LICENSE file in the root directory of this source tree.
6
 */
7
#pragma once
8
9
#include <cstddef>
10
#include <cstdint>
11
#include <cstring>
12
#include <memory>
13
#include <vector>
14
15
#include <faiss/impl/FaissAssert.h>
16
17
namespace faiss {
18
19
// An interface for an owner of a MaybeOwnedVector.
20
struct MaybeOwnedVectorOwner {
21
0
    virtual ~MaybeOwnedVectorOwner() = default;
22
};
23
24
// a container that either works as std::vector<T> that owns its own memory,
25
//    or as a view of a memory buffer, with a known size
26
template <typename T>
27
struct MaybeOwnedVector {
28
    using value_type = T;
29
    using self_type = MaybeOwnedVector<T>;
30
    using iterator = typename std::vector<T>::iterator;
31
    using const_iterator = typename std::vector<T>::const_iterator;
32
    using size_type = typename std::vector<T>::size_type;
33
34
    bool is_owned = true;
35
36
    // this one is used if is_owned == true
37
    std::vector<T> owned_data;
38
39
    // these three are used if is_owned == false
40
    T* view_data = nullptr;
41
    // the number of T elements
42
    size_t view_size = 0;
43
    // who owns the data.
44
    // This field can be nullptr, and it is present ONLY in order
45
    //   to avoid possible tricky memory / resource leaks.
46
    std::shared_ptr<MaybeOwnedVectorOwner> owner;
47
48
    // points either to view_data, or to owned.data()
49
    T* c_ptr = nullptr;
50
    // uses either view_size, or owned.size();
51
    size_t c_size = 0;
52
53
4.74k
    MaybeOwnedVector() = default;
_ZN5faiss16MaybeOwnedVectorIhEC2Ev
Line
Count
Source
53
2.39k
    MaybeOwnedVector() = default;
_ZN5faiss16MaybeOwnedVectorIiEC2Ev
Line
Count
Source
53
138
    MaybeOwnedVector() = default;
_ZN5faiss16MaybeOwnedVectorIlEC2Ev
Line
Count
Source
53
2.21k
    MaybeOwnedVector() = default;
54
0
    MaybeOwnedVector(const size_t initial_size) {
55
0
        is_owned = true;
56
57
0
        owned_data.resize(initial_size);
58
0
        c_ptr = owned_data.data();
59
0
        c_size = owned_data.size();
60
0
    }
61
62
    explicit MaybeOwnedVector(const std::vector<T>& vec)
63
            : faiss::MaybeOwnedVector<T>(vec.size()) {
64
        if (vec.size() > 0) {
65
            memcpy(owned_data.data(), vec.data(), sizeof(T) * vec.size());
66
        }
67
    }
68
69
0
    MaybeOwnedVector(const MaybeOwnedVector& other) {
70
0
        is_owned = other.is_owned;
71
0
        owned_data = other.owned_data;
72
73
0
        view_data = other.view_data;
74
0
        view_size = other.view_size;
75
0
        owner = other.owner;
76
77
0
        if (is_owned) {
78
0
            c_ptr = owned_data.data();
79
0
            c_size = owned_data.size();
80
0
        } else {
81
0
            c_ptr = view_data;
82
0
            c_size = view_size;
83
0
        }
84
0
    }
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIlEC2ERKS1_
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIhEC2ERKS1_
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIiEC2ERKS1_
85
86
0
    MaybeOwnedVector(MaybeOwnedVector&& other) {
87
0
        is_owned = other.is_owned;
88
0
        owned_data = std::move(other.owned_data);
89
90
0
        view_data = other.view_data;
91
0
        view_size = other.view_size;
92
0
        owner = std::move(other.owner);
93
0
        other.owner = nullptr;
94
95
0
        if (is_owned) {
96
0
            c_ptr = owned_data.data();
97
0
            c_size = owned_data.size();
98
0
        } else {
99
0
            c_ptr = view_data;
100
0
            c_size = view_size;
101
0
        }
102
0
    }
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIhEC2EOS1_
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIiEC2EOS1_
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIlEC2EOS1_
103
104
0
    MaybeOwnedVector& operator=(const MaybeOwnedVector& other) {
105
0
        if (this == &other) {
106
0
            return *this;
107
0
        }
108
109
        // create a copy
110
0
        MaybeOwnedVector cloned(other);
111
        // swap
112
0
        swap(*this, cloned);
113
114
0
        return *this;
115
0
    }
116
117
0
    MaybeOwnedVector& operator=(MaybeOwnedVector&& other) {
118
0
        if (this == &other) {
119
0
            return *this;
120
0
        }
121
122
        // moved
123
0
        MaybeOwnedVector moved(std::move(other));
124
        // swap
125
0
        swap(*this, moved);
126
127
0
        return *this;
128
0
    }
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIhEaSEOS1_
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIiEaSEOS1_
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIlEaSEOS1_
129
130
0
    MaybeOwnedVector(std::vector<T>&& other) {
131
0
        is_owned = true;
132
133
0
        owned_data = std::move(other);
134
0
        c_ptr = owned_data.data();
135
0
        c_size = owned_data.size();
136
0
    }
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIiEC2EOSt6vectorIiSaIiEE
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIlEC2EOSt6vectorIlSaIlEE
137
138
    static MaybeOwnedVector create_view(
139
            void* address,
140
            const size_t n_elements,
141
0
            const std::shared_ptr<MaybeOwnedVectorOwner>& owner) {
142
0
        MaybeOwnedVector vec;
143
0
        vec.is_owned = false;
144
0
        vec.view_data = reinterpret_cast<T*>(address);
145
0
        vec.view_size = n_elements;
146
0
        vec.owner = owner;
147
148
0
        vec.c_ptr = vec.view_data;
149
0
        vec.c_size = vec.view_size;
150
151
0
        return vec;
152
0
    }
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIhE11create_viewEPvmRKSt10shared_ptrINS_21MaybeOwnedVectorOwnerEE
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIlE11create_viewEPvmRKSt10shared_ptrINS_21MaybeOwnedVectorOwnerEE
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIiE11create_viewEPvmRKSt10shared_ptrINS_21MaybeOwnedVectorOwnerEE
153
154
40.4k
    const T* data() const {
155
40.4k
        return c_ptr;
156
40.4k
    }
_ZNK5faiss16MaybeOwnedVectorIhE4dataEv
Line
Count
Source
154
40.2k
    const T* data() const {
155
40.2k
        return c_ptr;
156
40.2k
    }
_ZNK5faiss16MaybeOwnedVectorIlE4dataEv
Line
Count
Source
154
134
    const T* data() const {
155
134
        return c_ptr;
156
134
    }
_ZNK5faiss16MaybeOwnedVectorIiE4dataEv
Line
Count
Source
154
25
    const T* data() const {
155
25
        return c_ptr;
156
25
    }
157
158
18.3k
    T* data() {
159
18.3k
        return c_ptr;
160
18.3k
    }
_ZN5faiss16MaybeOwnedVectorIhE4dataEv
Line
Count
Source
158
18.3k
    T* data() {
159
18.3k
        return c_ptr;
160
18.3k
    }
_ZN5faiss16MaybeOwnedVectorIlE4dataEv
Line
Count
Source
158
12
    T* data() {
159
12
        return c_ptr;
160
12
    }
_ZN5faiss16MaybeOwnedVectorIiE4dataEv
Line
Count
Source
158
20
    T* data() {
159
20
        return c_ptr;
160
20
    }
161
162
3.93k
    size_t size() const {
163
3.93k
        return c_size;
164
3.93k
    }
_ZNK5faiss16MaybeOwnedVectorIhE4sizeEv
Line
Count
Source
162
79
    size_t size() const {
163
79
        return c_size;
164
79
    }
_ZNK5faiss16MaybeOwnedVectorIiE4sizeEv
Line
Count
Source
162
25
    size_t size() const {
163
25
        return c_size;
164
25
    }
_ZNK5faiss16MaybeOwnedVectorIlE4sizeEv
Line
Count
Source
162
3.83k
    size_t size() const {
163
3.83k
        return c_size;
164
3.83k
    }
165
166
    size_t byte_size() const {
167
        return c_size * sizeof(T);
168
    }
169
170
72.4M
    T& operator[](const size_t idx) {
171
72.4M
        return c_ptr[idx];
172
72.4M
    }
_ZN5faiss16MaybeOwnedVectorIhEixEm
Line
Count
Source
170
3.58k
    T& operator[](const size_t idx) {
171
3.58k
        return c_ptr[idx];
172
3.58k
    }
_ZN5faiss16MaybeOwnedVectorIiEixEm
Line
Count
Source
170
72.4M
    T& operator[](const size_t idx) {
171
72.4M
        return c_ptr[idx];
172
72.4M
    }
_ZN5faiss16MaybeOwnedVectorIlEixEm
Line
Count
Source
170
3.55k
    T& operator[](const size_t idx) {
171
3.55k
        return c_ptr[idx];
172
3.55k
    }
173
174
668k
    const T& operator[](const size_t idx) const {
175
668k
        return c_ptr[idx];
176
668k
    }
_ZNK5faiss16MaybeOwnedVectorIhEixEm
Line
Count
Source
174
498
    const T& operator[](const size_t idx) const {
175
498
        return c_ptr[idx];
176
498
    }
_ZNK5faiss16MaybeOwnedVectorIiEixEm
Line
Count
Source
174
667k
    const T& operator[](const size_t idx) const {
175
667k
        return c_ptr[idx];
176
667k
    }
177
178
    T& at(size_type pos) {
179
        FAISS_ASSERT_MSG(
180
                is_owned,
181
                "This operation cannot be performed on a viewed vector");
182
183
        return owned_data.at(pos);
184
    }
185
186
    const T& at(size_type pos) const {
187
        FAISS_ASSERT_MSG(
188
                is_owned,
189
                "This operation cannot be performed on a viewed vector");
190
191
        return owned_data.at(pos);
192
    }
193
194
    iterator begin() {
195
        FAISS_ASSERT_MSG(
196
                is_owned,
197
                "This operation cannot be performed on a viewed vector");
198
199
        return owned_data.begin();
200
    }
201
202
    const_iterator begin() const {
203
        FAISS_ASSERT_MSG(
204
                is_owned,
205
                "This operation cannot be performed on a viewed vector");
206
207
        return owned_data.begin();
208
    }
209
210
0
    iterator end() {
211
0
        FAISS_ASSERT_MSG(
212
0
                is_owned,
213
0
                "This operation cannot be performed on a viewed vector");
214
215
0
        return owned_data.end();
216
0
    }
217
218
    const_iterator end() const {
219
        FAISS_ASSERT_MSG(
220
                is_owned,
221
                "This operation cannot be performed on a viewed vector");
222
223
        return owned_data.end();
224
    }
225
226
    iterator erase(const_iterator begin, const_iterator end) {
227
        FAISS_ASSERT_MSG(
228
                is_owned,
229
                "This operation cannot be performed on a viewed vector");
230
231
        auto result = owned_data.erase(begin, end);
232
        c_ptr = owned_data.data();
233
        c_size = owned_data.size();
234
235
        return result;
236
    }
237
238
    template <class InputIt>
239
0
    iterator insert(const_iterator pos, InputIt first, InputIt last) {
240
0
        FAISS_ASSERT_MSG(
241
0
                is_owned,
242
0
                "This operation cannot be performed on a viewed vector");
243
244
0
        auto result = owned_data.insert(pos, first, last);
245
0
        c_ptr = owned_data.data();
246
0
        c_size = owned_data.size();
247
248
0
        return result;
249
0
    }
250
251
297
    void clear() {
252
297
        FAISS_ASSERT_MSG(
253
297
                is_owned,
254
297
                "This operation cannot be performed on a viewed vector");
255
256
297
        owned_data.clear();
257
297
        c_ptr = owned_data.data();
258
297
        c_size = owned_data.size();
259
297
    }
_ZN5faiss16MaybeOwnedVectorIhE5clearEv
Line
Count
Source
251
297
    void clear() {
252
297
        FAISS_ASSERT_MSG(
253
297
                is_owned,
254
297
                "This operation cannot be performed on a viewed vector");
255
256
297
        owned_data.clear();
257
297
        c_ptr = owned_data.data();
258
297
        c_size = owned_data.size();
259
297
    }
Unexecuted instantiation: _ZN5faiss16MaybeOwnedVectorIiE5clearEv
260
261
25.4k
    void resize(const size_t new_size) {
262
25.4k
        FAISS_ASSERT_MSG(
263
25.4k
                is_owned,
264
25.4k
                "This operation cannot be performed on a viewed vector");
265
266
25.4k
        owned_data.resize(new_size);
267
25.4k
        c_ptr = owned_data.data();
268
25.4k
        c_size = owned_data.size();
269
25.4k
    }
_ZN5faiss16MaybeOwnedVectorIhE6resizeEm
Line
Count
Source
261
21.9k
    void resize(const size_t new_size) {
262
21.9k
        FAISS_ASSERT_MSG(
263
21.9k
                is_owned,
264
21.9k
                "This operation cannot be performed on a viewed vector");
265
266
21.9k
        owned_data.resize(new_size);
267
21.9k
        c_ptr = owned_data.data();
268
21.9k
        c_size = owned_data.size();
269
21.9k
    }
_ZN5faiss16MaybeOwnedVectorIlE6resizeEm
Line
Count
Source
261
3.49k
    void resize(const size_t new_size) {
262
3.49k
        FAISS_ASSERT_MSG(
263
3.49k
                is_owned,
264
3.49k
                "This operation cannot be performed on a viewed vector");
265
266
3.49k
        owned_data.resize(new_size);
267
3.49k
        c_ptr = owned_data.data();
268
3.49k
        c_size = owned_data.size();
269
3.49k
    }
_ZN5faiss16MaybeOwnedVectorIiE6resizeEm
Line
Count
Source
261
20
    void resize(const size_t new_size) {
262
20
        FAISS_ASSERT_MSG(
263
20
                is_owned,
264
20
                "This operation cannot be performed on a viewed vector");
265
266
20
        owned_data.resize(new_size);
267
20
        c_ptr = owned_data.data();
268
20
        c_size = owned_data.size();
269
20
    }
270
271
18.0k
    void resize(const size_t new_size, const value_type v) {
272
18.0k
        FAISS_ASSERT_MSG(
273
18.0k
                is_owned,
274
18.0k
                "This operation cannot be performed on a viewed vector");
275
276
18.0k
        owned_data.resize(new_size, v);
277
18.0k
        c_ptr = owned_data.data();
278
18.0k
        c_size = owned_data.size();
279
18.0k
    }
280
281
0
    friend void swap(self_type& a, self_type& b) {
282
0
        std::swap(a.is_owned, b.is_owned);
283
0
        std::swap(a.owned_data, b.owned_data);
284
0
        std::swap(a.view_data, b.view_data);
285
0
        std::swap(a.view_size, b.view_size);
286
0
        std::swap(a.owner, b.owner);
287
0
        std::swap(a.c_ptr, b.c_ptr);
288
0
        std::swap(a.c_size, b.c_size);
289
0
    }
Unexecuted instantiation: _ZN5faiss4swapERNS_16MaybeOwnedVectorIhEES2_
Unexecuted instantiation: _ZN5faiss4swapERNS_16MaybeOwnedVectorIiEES2_
Unexecuted instantiation: _ZN5faiss4swapERNS_16MaybeOwnedVectorIlEES2_
290
};
291
292
template <typename T>
293
struct is_maybe_owned_vector : std::false_type {};
294
295
template <typename T>
296
struct is_maybe_owned_vector<MaybeOwnedVector<T>> : std::true_type {};
297
298
template <typename T>
299
inline constexpr bool is_maybe_owned_vector_v = is_maybe_owned_vector<T>::value;
300
301
template <typename T>
302
bool operator==(
303
        const MaybeOwnedVector<T>& lhs,
304
        const MaybeOwnedVector<T>& rhs) {
305
    return lhs.size() == rhs.size() &&
306
            !memcmp(lhs.data(), rhs.data(), lhs.byte_size());
307
}
308
309
template <typename T>
310
bool operator!=(
311
        const MaybeOwnedVector<T>& lhs,
312
        const MaybeOwnedVector<T>& rhs) {
313
    return !(lhs == rhs);
314
}
315
316
} // namespace faiss