@Override
	public <T> AddressSet computeVisibleParts(AddressSetView set, Lifespan lifespan, T object,
			Occlusion<T> occlusion) {
		List<Lifespan> spans;
		try (LockHold hold = trace.lockRead()) {
			if (!containsAnyUpper(lifespan)) {
				return new AddressSet();
			}
			spans = getOrderedSpans();
		}
		AddressSet remains = new AddressSet(set);
		for (Lifespan rng : spans) {
			if (lifespan.contains(rng.lmax())) {
				return remains;
			}
			occlusion.remove(object, remains, rng);
			if (remains.isEmpty()) {
				return remains;
			}
		}
		// This condition should have been detected by !containsAnyUpper
		throw new AssertionError();
	}
NB. Because occlusion.occluded can be expensive, we should only keep the lock long enough
to copy the spans.
Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTraceTimeViewport.java