Composing graph resources via Query Cache objects

Hi all, (but especially @ben.boeckel for your link-loader knowledge…)

One of the discussions @tj.corona and I had about SMTK was composing a new graph-resource class by importing node and arc types from other, preexisting resource classes. For example aeva wants to import OpenCascade node types (so it can use OpenCascade to import STEP/IGES files and display them) but it also wants to add new node types specific to aeva.

The issue is that each session (aeva, opencascade) typically has a Session class owned by the Resource that holds modeling-kernel-specific data. When composing nodes and arcs, all of the Session instances need to be available to the various nodes and operations. My thought was to use the query Cache to hold this data. Anyone can fetch a Cache from a Resource's Queries object as long as it knows the Cache's type. TJ was worried that this could lead to problems with symbol visibility/duplication. Specifically, the smtk::session::opencascade::Resource class might live in one shared library/plugin while the smtk::session::aeva::Resource might live in another. TJ was worried that this:


namespace smtk::session::opencascade
{
class Cache; // Map between OpenCascade model kernel and SMTK components
class Surface; // SMTK graph-node component type that accesses opencascade::Cache.
class Resource; // Resource for CAD models
}

namespace smtk::session::aeva {
class Cache; // Map between aeva's VTK-data and SMTK components
class Image; // SMTK graph-node component type that accesses aeva::Cache
class Resource;

std::shared_ptr<Resource> resource;
auto foo = resource.find<opencascade::Surface>(uuid1);
auto bar = resource.find<aeva::Image>(uuid1);
foo->doSomething(); // calls resource->queries().cache<opencascade::Cache>()
bar->doSomethingElse(); // calls resource->queries().cache<aeva::Cache>()
}

would have problems because the Queries container would be holding objects from different shared libraries. Do you see this as an issue? Are there ways around it?

Containers don’t care that elements “live” in different shared libraries. We do this all the time in VTK or ParaView when a filter from, say, FiltersCore and FiltersGeneral both reside beside each other in a container. As long as the interface is shared between them (i.e., the built against the same header/library), there shouldn’t be any problems.

However, the problem here is that you’re expecting templated instances to be called; the call site must know about both resource types at compile time for that to work.

Note that this is OK because library unloading is basically disallowed in practice. If that is to be supported, there would need to be a mechanism to “stop the world” and nuke all instances of objects or data which are referring to the to-be-unloaded library’s code. This includes callbacks and signal/slot connections.