protected List<ROW_OBJECT> doFilter(List<ROW_OBJECT> data,
			TableSortingContext<ROW_OBJECT> lastSortingContext, TaskMonitor monitor)
			throws CancelledException {

		// copy the filter so that it is not changed by another thread whilst this filter is
		// taking place

		if (data.size() == 0) {
			return data;
		}

		if (!hasFilter()) {
			return data;
		}

		monitor.initialize(data.size());

		TableFilter<ROW_OBJECT> filterCopy = getTableFilter();
		List<ROW_OBJECT> filteredList = new ArrayList<>();
		for (int row = 0; row < data.size(); row++) {
			if (monitor.isCancelled()) {
				return filteredList; // cancelled just return what has matches so far
			}

			ROW_OBJECT rowObject = data.get(row);
			if (filterCopy.acceptsRow(rowObject)) {
				filteredList.add(rowObject);
			}
			monitor.incrementProgress(1);
		}

		return filteredList;
	}
Override this to change how filtering is performed.  This implementation will do nothing
if a <code>TableFilter</code> has not been set via a call to
{@link #setTableFilter(TableFilter)}.

@param data The list of data to be filtered.
@param monitor the progress monitor to check for cancellation.
@param lastSortingContext the comparator used to sort data.  This can be used by overridden
                  filter methods that need to query data about how the table is sorted.
@return The <b>new</b> filtered list of data.  If no filtering takes place, then the
	       original list should be returned.
@throws CancelledException If the filter operation is cancelled.
Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/ThreadedTableModel.java