Yes, in the current architecture, the device world is copied for the layout/explorer view, and also for tiled builds. This means that each device is essentially deep copied, which is OK for lightweight but not, as you note, for heavyweight.
If it is a simple read-only resource (like a loaded file), then a shared resource via smart pointer/reference counting is the best way to share the resource. More heavyweight shared resources might need a separate resource manager class (the Tiled File Input device does this because it is managing a much more complicated set of files, caching, etc)
Anyways.
In the 2.2 codebase, shared resources are manually reference counted. For example, the File Input device does something like the below.
In the device’s doClone() function (polymorphic copy constructor)
...
HField *resource = other->resource;
if (resource )
resource ->AddRef();
in the device’s destructor:
if (resource )
resource ->Release();
as long as all accesses are read-only, the WMPacket-based objects are thread-safe while shared. If you are writing to the resource you should manually protect it with mutual exclusion.
A last note: In the upcoming WM 2.3 codebase, all raw pointers are internally wrapped in a boost::intrusive_ptr to automatically call AddRef() and Release() as appropriate .