docs: @Override
  	public void close() {
  		// check if the sorter has been closed before
  		synchronized (this) {
  			if (this.closed) {
  				return;
  			}
  
  			// mark as closed
  			this.closed = true;
  		}
  
  		// from here on, the code is in a try block, because even through errors might be thrown in this block,
  		// we need to make sure that all the memory is released.
  		try {
  			// if the result iterator has not been obtained yet, set the exception
  			synchronized (this.iteratorLock) {
  				if (this.iteratorException == null) {
  					this.iteratorException = new IOException("The sorter has been closed.");
  					this.iteratorLock.notifyAll();
  				}
  			}
  
  			// stop all the threads
  			if (this.sortThread != null) {
  				try {
  					this.sortThread.shutdown();
  				} catch (Throwable t) {
  					LOG.error("Error shutting down sorter thread: " + t.getMessage(), t);
  				}
  			}
  			if (this.spillThread != null) {
  				try {
  					this.spillThread.shutdown();
  				} catch (Throwable t) {
  					LOG.error("Error shutting down spilling thread: " + t.getMessage(), t);
  				}
  			}
  			if (this.mergeThread != null) {
  				try {
  					this.mergeThread.shutdown();
  				} catch (Throwable t) {
  					LOG.error("Error shutting down merging thread: " + t.getMessage(), t);
  				}
  			}
  
  			try {
  				if (this.sortThread != null) {
  					this.sortThread.join();
  					this.sortThread = null;
  				}
  				if (this.spillThread != null) {
  					this.spillThread.join();
  					this.spillThread = null;
  				}
  				if (this.mergeThread != null) {
  					this.mergeThread.join();
  					this.mergeThread = null;
  				}
  			} catch (InterruptedException iex) {
  				LOG.debug("Closing of sort/merger was interrupted. " +
  						"The reading/sorting/spilling/merging threads may still be working.", iex);
  			}
  		} finally {
  			releaseSortMemory();
  
  			// Eliminate object references for MemorySegments.
  			circularQueues = null;
  			currWriteBuffer = null;
  			iterator = null;
  
  			merger.close();
  			channelManager.close();
  		}
  	}