Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::view::ViewPool Class Reference

Per-class recycling pool for View objects. More...

#include <view_pool.hpp>

Public Member Functions

 ViewPool ()=default
 ViewPool (std::size_t per_class_cap)
 ViewPool (const ViewPool &)=delete
ViewPool & operator= (const ViewPool &)=delete
template<class T, class Factory>
std::unique_ptr< T > acquire (Factory &&make)
 Acquire a T.
std::unique_ptr< View > acquire (std::type_index key)
 Type-erased acquire for callers that do not know the concrete row/cell type at compile time (VirtualList / VirtualGrid drive a user factory that returns a base View).
void release (std::unique_ptr< View > view)
 Return a view to the pool.
void set_per_class_cap (std::size_t cap)
 Set the maximum number of pooled instances per class.
std::size_t per_class_cap () const
void clear ()
 Drop every pooled instance across all classes.
std::size_t size (std::type_index key) const
 Number of pooled instances of a given class (introspection / tests).
std::size_t total_size () const
 Total pooled instances across all classes (introspection / tests).

Static Public Attributes

static constexpr std::size_t kDefaultPerClassCap = 32
 Default per-class free-list cap.

Detailed Description

Per-class recycling pool for View objects.

A ViewPool keeps a bounded free-list per concrete View subclass, keyed by std::type_index. Recycling avoids the allocate/construct/destroy churn that dominates large virtualized lists/grids and scripted-UI hot reloads: instead of destroying a row/cell View when it scrolls out of view and building a fresh one when it scrolls back in, the pool hands the same object back after View::prepare_for_reuse() scrubs its per-instance state.

Ownership model — INSTANCE-OWNED, never a process-global singleton. A process-global pool would outlive the ScriptEngines / view trees that populate it and invite stale-callback use-after-free: a recycled view could hold a std::function capturing state from a torn-down engine. Each owner (VirtualList, VirtualGrid, a future hot-reload recycler) holds its own ViewPool whose lifetime is bounded by the owner's, so the free-list drains when the owner dies.

Opt-in only. release() stores a view only when view->supports_reuse() returns true; every other view is destroyed immediately, exactly as it would be without a pool. This keeps adoption behavior-neutral: a subclass that does not override supports_reuse() is never pooled.

Not thread-safe. All access must happen on the UI thread that owns the view tree, the same constraint the View hierarchy already imposes.

Constructor & Destructor Documentation

◆ ViewPool() [1/3]

pulp::view::ViewPool::ViewPool ( )
default

◆ ViewPool() [2/3]

pulp::view::ViewPool::ViewPool ( std::size_t per_class_cap)
inlineexplicit

◆ ViewPool() [3/3]

pulp::view::ViewPool::ViewPool ( const ViewPool & )
delete

Member Function Documentation

◆ acquire() [1/2]

template<class T, class Factory>
std::unique_ptr< T > pulp::view::ViewPool::acquire ( Factory && make)
inline

Acquire a T.

Pops a recycled instance from the typeid(T) free-list, calls prepare_for_reuse() on it, and returns it. When the free-list is empty, calls make() (which must return std::unique_ptr<T>) and returns its result unmodified.

The pool only ever stores views under their DYNAMIC type (see release()), so a hit here is guaranteed to be an object whose most- derived type is exactly T — the static_cast is safe and there is no cross-class handout.

◆ acquire() [2/2]

std::unique_ptr< View > pulp::view::ViewPool::acquire ( std::type_index key)

Type-erased acquire for callers that do not know the concrete row/cell type at compile time (VirtualList / VirtualGrid drive a user factory that returns a base View).

Returns a recycled, reuse-prepared view whose dynamic type is exactly key, or nullptr when the free-list is empty.

◆ clear()

void pulp::view::ViewPool::clear ( )
inline

Drop every pooled instance across all classes.

◆ operator=()

ViewPool & pulp::view::ViewPool::operator= ( const ViewPool & )
delete

◆ per_class_cap()

std::size_t pulp::view::ViewPool::per_class_cap ( ) const
inline

◆ release()

void pulp::view::ViewPool::release ( std::unique_ptr< View > view)

Return a view to the pool.

Keyed by the view's DYNAMIC type. The view is stored only when it opts in via supports_reuse() AND the class free-list is under the per-class cap; otherwise it is destroyed here. prepare_for_ reuse() is deliberately NOT called on this path — it runs on the next acquire() so a pooled view carries no live callbacks while parked, and the reset cost is paid only for views that are actually reused.

◆ set_per_class_cap()

void pulp::view::ViewPool::set_per_class_cap ( std::size_t cap)
inline

Set the maximum number of pooled instances per class.

Does not evict entries already over the new cap; they drain naturally on acquire().

◆ size()

std::size_t pulp::view::ViewPool::size ( std::type_index key) const
inline

Number of pooled instances of a given class (introspection / tests).

◆ total_size()

std::size_t pulp::view::ViewPool::total_size ( ) const
inline

Total pooled instances across all classes (introspection / tests).

Member Data Documentation

◆ kDefaultPerClassCap

std::size_t pulp::view::ViewPool::kDefaultPerClassCap = 32
staticconstexpr

Default per-class free-list cap.

Sized to comfortably cover a viewport's worth of recycled rows/cells plus overscan without unbounded retention.


The documentation for this class was generated from the following file:
  • /home/runner/work/pulp/pulp/core/view/include/pulp/view/view_pool.hpp