public synchronized void add(Range r) {
    	Set<Range> toDelete = new HashSet<Range>();
    	boolean span = false;
    	for(Range currentRange: this.ranges) {
    		if (r.getLow() <= currentRange.getHigh() + 1 && r.getLow() >= currentRange.getLow()) {
    			// if the current range will merge with the low-end of r, set r's low to currentRange's low and delete currentRange
    			r.setLow(currentRange.getLow());
    			toDelete.add(currentRange);
    			span = true;
    		} else if (r.getHigh() >= currentRange.getLow() - 1 && r.getHigh() <= currentRange.getHigh()) {
    			// if the current range will merge with the high-end of r, set r's high to currentRange's high and delete currentRange
    			r.setHigh(currentRange.getHigh());
    			toDelete.add(currentRange);
    			span = false;
    		} else if (span && currentRange.getHigh() < r.getHigh()) {
    			// if currentRange is spanned entirely by r
    			toDelete.add(currentRange);
    		}
    	}

    	// do not allow reading of this.ranges while we perform the adds and deletes
    	this.lock.writeLock().lock();
    	try {
    		this.ranges.removeAll(toDelete);
    		this.ranges.add(r);
    	} finally {
    		this.lock.writeLock().unlock();
    	}
    }