template <typename Record>
class PagedView
Defined at line 96 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
PagedView is an adapter for a set of PMM memory pages that provides typed "views" into these
pages. The view does not own the lifetime of these pages, so it should not be used once the pages
have been deallocated.
Internally, it operates page-at-a-time, so it is safe to deallocate and unlink pages
above or below the current page (as returned by the current_page() method).
There are three different interfaces, which can be mixed as needed:
// Assume for the examples below:
assert(ZX_OK == pmm_alloc_pages(num_pages,
&page
_list));
struct MyNode { int foo; };
fbl::PagedView
<MyNode
> paged_view(page_list);
1. Record-at-a-time: Good for building data when the producer drives the loop.
The pattern is:
for ( /* producer loop */ ) {
paged_view.record().foo = x;
if (!paged_view.next_record()) {
// Reached the end of the allocated pages. This is either a logical error (not enough
// pages were allocated) or is by design, and we need to "consume" the data and
// somehow resume the producer loop.
}
}
2. Page-at-a-time: Good for consuming the data in the pages. The pattern is:
do {
for (auto
&
node : paged_view.span()) {
consume_data(.., node.foo, ..);
}
} while(paged_view.next_page());
Note that span() returns all the memory of that page. If a particular page
has not been fully initialized, you should use the marker mode below.
3. Marker mode: Allows saving a cursor and returning to it. Applicable to either of
the above forms but easier to see in the second case:
// Assume we allocated exactly the number of pages needed.
for ( /* producer loop */ ) {
paged_view.record().foo = x;
assert(paged_view.next_record());
}
// The producer is done. Now we need to consume however many nodes have been added;
// however, the last page might not be full. We can handle that by getting a marker
// and resetting the internal cursor.
auto marker = paged_view.reset();
do {
for (auto
&
node : paged_view.span(marker)) {
consume_data(.., node.foo, ..);
}
if (paged_view.marker_in_page(marker)) break;
} while(paged_view.next_page());
// Note the use of span(marker) rather than just span(), so that for the last
// page, the correct number of records are returned.
Marker Direction
The markers come in two flavors, referred to below as "direction of travel". The reset() method
returns a "from-start" marker that can be used to iterate from the first record to the last
record that was current at the reset() callsite. This is what the last example above shows.
Also, you can use get_marker_to_end() to obtain a "to-end" marker, which can be used to iterate
from the currently active record to the last record.
The correct use of both these markers is guaranteed by using the for_each_page() method, or its
source can be inspected to roll your own version.
Public Members
static const uint32_t kMaxCount
Public Methods
void PagedView<Record> (list_node * list)
Creates the paged view. An assert will fire if the list is empty.
Defined at line 121 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
Record & record ()
Returns the current record.
Defined at line 126 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
bool next_record ()
Moves the internal cursor to the next record. Returns false if the cursor has moved past the
last record, true otherwise.
Defined at line 130 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
ktl::span<Record> span ()
Returns a span to the entire current page.
Defined at line 139 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
ktl::span<Record> span_first ()
Returns a span that covers from the start of the current page to the cursor.
Defined at line 141 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
ktl::span<Record> span_last ()
Returns a span that covers from the cursor to the end of the page.
Defined at line 143 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
ktl::span<Record> span (const Marker & marker)
Returns a span modulated by the |marker|. If the marker points to a different page, then the
span returned is the full span of the current page. If the marker points to the current page,
then the span returned is from the top of the page if Marker::direction() is kFromStart, or it
returns the span from the marker to the end of the page if the direction is kToEnd.
Defined at line 149 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
Marker reset (vm_page_t * start, uint32_t start_index)
Resets the PagedView internal cursor to the |start| + |start_index| position and returns
a from-start marker to the previous cursor. The |start| page must be in the list of
pages given to the constructor of PagedView.
Defined at line 160 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
Marker reset (const Marker & marker)
Resets the PagedView to the location indicated by |marker| and returns a from-start marker
to the previous cursor position. The direction of travel of |marker| is ignored.
Defined at line 173 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
Marker get_marker_from_start ()
Gets a marker to the current position, of type from-start, that can be passed to reset() or
to span().
Defined at line 180 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
Marker get_marker_to_end (uint32_t skip)
Gets a marker to the current position, of type to-end, that can be passed to reset() or to
span().
Defined at line 186 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
bool marker_in_page (const Marker & marker)
Returns true if the marker points to the PagedView's current page.
Defined at line 191 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
vm_page_t * current_page ()
Returns the current page. Do not free this page if you are going to call other methods.
Defined at line 194 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
uint32_t current_index ()
Returns the current index, relative to the start of current_page().
Defined at line 196 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
vm_page_t * next_page ()
Moves to the next page. Returns the new current page, or null if the end of the list is
reached.
Defined at line 200 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
template <typename Fn>
void for_each_page (Fn fn)
Repeatedly calls |fn| with the full span of each page.
Defined at line 207 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
template <typename Fn>
void for_each_page (const Marker & marker, Fn fn)
Repeatedly calls |fn| with the pages indicated by |marker|. If the marker is from-start,
fn is called with all the pages from the first page to the marker. If the marker is to-end, fn
is called with all the pages from the cursor to the last page.
Defined at line 217 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h
vm_page_t * move (int32_t count)
Moves the internal cursor forward or backward by |count| records. The runtime is O(n) in the
number of pages. On success, it returns the page that is now current. Returns null if moving
past the last record or before the first record.
Defined at line 237 of file ../../zircon/kernel/lib/fbl/include/fbl/paged_view.h