@Override
	default int getNumComponents() {
		try (LockHold hold = LockHold.lock(getTrace().getReadWriteLock().readLock())) {
			if (getLength() < getDataType().getLength()) {
				return -1;
			}
			DataType baseDataType = getBaseDataType();
			if (baseDataType instanceof Composite) {
				return ((Composite) baseDataType).getNumComponents();
			}
			if (baseDataType instanceof Array) {
				return ((Array) baseDataType).getNumElements();
			}
			if (baseDataType instanceof DynamicDataType) {
				try {
					return ((DynamicDataType) baseDataType).getNumComponents(this);
				}
				catch (Exception e) {
					// TODO: Why does the original use Throwable?
					return 0;
				}
			}
			return 0;
		}
	}
TODO: Document me

Note this will always be called with the write lock

@return the new or existing component cache
Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/listing/DBTraceDefinedDataAdapter.java