protected List<Match> growMatches(int threshold, boolean stopAtFirstMatch)
	{
		List<Match> result = new ArrayList<Match>();
		/**
		 * The main process is the merging (growing) of matches.
		 * <p>
		 * Note that after each cycle, the chosen match will not exist any more - it is removed from the queue and from
		 * all the candidate's candidates list - it will either grow (by merging with various candidates) or disappear
		 * completely.
		 */
		while(!matchQueue.isEmpty())
		{
			Match m = matchQueue.poll(); // matches are sorted according to the criteria above
			if(!m.isValid())
				continue;
			for(Iterator<Match> itm = m.mergeCandidates.iterator(); itm.hasNext();)
			{
				// remove the candidate from the list, and the current match from the candidate's list
				Match mc = itm.next();
				itm.remove();
				if(!mc.isValid())
					continue;
				mc.mergeCandidates.remove(m);
				monitor.lf("merging \t []\n \t\t\t and \t\t []", m, mc);
				Match mr = addMergeMatch(m, mc);
				if(mr != null) // merge should never fail
				{
					monitor.lf("new match:\t []\n", mr);
					if(monitor.getVisual() != null)
						monitor.getVisual().feedLine(m, mc, mr, "new match [k=" + mr.k + "]");
					monitor.incrementMergeCount();
					monitor.incrementMatchCount();
					if(mr.k <= threshold)
					{
						result.add(mr);
						if(stopAtFirstMatch)
							return result;
					}
				}
				else
				{
					monitor.le("merge failed\n");
					if(monitor.getVisual() != null)
						monitor.getVisual().feedLine("merge failed");
				}
			}
		}
		return result;
	}