Skip to content

Commit 12c25cf

Browse files
authored
Add entry_at(i) accessor to LoadBackendOptionsMap (#19645)
Differential Revision: D105100370 Pull Request resolved: #19645
1 parent 0a82163 commit 12c25cf

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

runtime/backend/backend_options_map.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <executorch/runtime/backend/options.h>
1212
#include <executorch/runtime/core/error.h>
1313
#include <executorch/runtime/core/span.h>
14+
#include <executorch/runtime/platform/assert.h>
1415

1516
#include <cstring>
1617

@@ -171,6 +172,46 @@ class LoadBackendOptionsMap final {
171172
return size_;
172173
}
173174

175+
/**
176+
* Non-owning view of a single (backend_id, options) entry, returned by
177+
* entry_at(). The pointer / span are valid until the map is mutated or
178+
* destroyed.
179+
*/
180+
struct EntryView {
181+
const char* backend_id = nullptr;
182+
Span<const BackendOption> options;
183+
};
184+
185+
/**
186+
* Returns the (backend_id, options) entry at the given index for
187+
* enumeration over the map's contents.
188+
*
189+
* @param index The entry index. Must be < size(); behavior is undefined
190+
* otherwise. Use this together with size() to walk every entry.
191+
* @return EntryView referencing the entry's backend_id and options. The
192+
* view is valid until the next mutation of, or destruction of, this
193+
* map.
194+
*
195+
* Example:
196+
* @code
197+
* for (size_t i = 0; i < map.size(); ++i) {
198+
* const auto entry = map.entry_at(i);
199+
* // use entry.backend_id and entry.options ...
200+
* }
201+
* @endcode
202+
*/
203+
EntryView entry_at(size_t index) const {
204+
ET_DCHECK_MSG(
205+
index < size_,
206+
"entry_at index %zu out of bounds (size=%zu)",
207+
index,
208+
size_);
209+
return EntryView{
210+
entries_[index].backend_id,
211+
Span<const BackendOption>(
212+
entries_[index].options.data(), entries_[index].options.size())};
213+
}
214+
174215
private:
175216
static constexpr size_t kMaxBackends = 8;
176217
static constexpr size_t kMaxBackendIdLength = 64;

runtime/backend/test/backend_options_map_test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,32 @@ TEST_F(LoadBackendOptionsMapTest, SetOptionsWithBuilderUpdatesExisting) {
365365
}
366366
EXPECT_EQ(num_threads2, 8); // Should be updated value
367367
}
368+
369+
// Test entry_at returns each (backend_id, options) pair in insertion order
370+
// and the spans reference the same data the corresponding get_options
371+
// calls return.
372+
TEST_F(LoadBackendOptionsMapTest, EntryAtEnumeratesAllEntries) {
373+
LoadBackendOptionsMap map;
374+
375+
BackendOptions<2> opts1;
376+
opts1.set_option("k1", 1);
377+
ASSERT_EQ(map.set_options("BackendA", opts1.view()), Error::Ok);
378+
379+
BackendOptions<2> opts2;
380+
opts2.set_option("k2", true);
381+
opts2.set_option("k3", "v");
382+
ASSERT_EQ(map.set_options("BackendB", opts2.view()), Error::Ok);
383+
384+
ASSERT_EQ(map.size(), 2u);
385+
386+
const auto e0 = map.entry_at(0);
387+
EXPECT_STREQ(e0.backend_id, "BackendA");
388+
EXPECT_EQ(e0.options.size(), 1u);
389+
// Spans returned by entry_at point at the same storage as get_options.
390+
EXPECT_EQ(e0.options.data(), map.get_options("BackendA").data());
391+
392+
const auto e1 = map.entry_at(1);
393+
EXPECT_STREQ(e1.backend_id, "BackendB");
394+
EXPECT_EQ(e1.options.size(), 2u);
395+
EXPECT_EQ(e1.options.data(), map.get_options("BackendB").data());
396+
}

0 commit comments

Comments
 (0)