LineGridCanvasPanel 2.3: The Widget Pool System

The pool sytem is exposed through API endpoints. It does not automatically rewrite every child workflow by itself. The base class gives future SpawnInViewWidgets() / RemoveOutOfViewWidgets() implementations a clean way to opt into pooling.

With bUseWidgetPool = true:

AcquireChildWidgetFromPool(Class, DataObject) does this:

  1. Checks ObjectToSmartChildWidgetMap first.
  2. If that DataObject already has an active widget, returns it.
  3. Otherwise checks the pool bucket for the exact widget class.
  4. If a pooled widget exists, reuses it.
  5. If not, calls CreateWidget.
  6. Calls SetDataObject(DataObject) before registration.
  7. Calls the child acquire hook.
  8. Calls AddAndRegisterSmartWidget.
  9. Requests child layout refresh.

ReleaseChildWidgetToPool(Child) does this:

  1. Verifies the child is actively registered under its current GetDataObject().
  2. Calls DeRegisterSmartChild, removing it from the canvas and ObjectToSmartChildWidgetMap.
  3. Calls the child release hook.
  4. Clears the data object with SetDataObject(nullptr).
  5. Stores it in the exact class bucket only if that bucket is below its max.
  6. If the bucket is full, the widget is dropped and can be garbage collected.

With bUseWidgetPool = false:

You can still call the same API, but it behaves like a non-retaining lifecycle.

AcquireChildWidgetFromPool(...) still:

  • checks the active map first,
  • then creates a widget if needed.

But it does not reuse inactive pooled widgets.

ReleaseChildWidgetToPool(...) still:

  • deregisters safely,
  • clears the data object,
  • calls the child release hook,

but it does not store the widget for reuse.

So if someone does not want pooling, they can either:

  • set bUseWidgetPool = false and still use the same acquire/release API, or
  • ignore the pool API completely and use CreateWidget, AddAndRegisterSmartWidget, and DeRegisterSmartChild manually.

The intended pooled virtualization pattern is:

				
					RemoveOutOfViewWidgets(...)
{
    // For active children no longer in view:
    ReleaseChildWidgetToPool(Child);
}

SpawnInViewWidgets(...)
{
    // For data objects now in view:
    if (!GetActiveLineGridChildWidgetForDataObject(DataObject))
    {
        Child = AcquireChildWidgetFromPool(WidgetClass, DataObject);
        // configure logical spans / visuals
    }
}