docs: public void run() {
  		boolean isActive = true;
  
  		//
  		// if interrupted (unlikely), end thread
  		//
  		try {
  			//
  			// loop until the AsyncAppender is closed.
  			//
  			while (isActive) {
  				LoggingEvent[] events = null;
  
  				//
  				// extract pending events while synchronized
  				// on buffer
  				//
  				synchronized (buffer) {
  					int bufferSize = buffer.size();
  					isActive = !isAsyncAppenderClosed(parent);
  
  					while ((bufferSize == 0) && isActive) {
  						buffer.wait();
  						bufferSize = buffer.size();
  						isActive = !isAsyncAppenderClosed(parent);
  					}
  
  					if (bufferSize > 0) {
  						events = new LoggingEvent[bufferSize + discardMap.size()];
  						buffer.toArray(events);
  
  						//
  						// add events due to buffer overflow
  						//
  						int index = bufferSize;
  
  						for (Iterator iter = discardMap.values().iterator(); iter.hasNext();) {
  							events[index++] = ((DiscardSummary) iter.next()).createEvent();
  						}
  
  						//
  						// clear buffer and discard map
  						//
  						buffer.clear();
  						discardMap.clear();
  
  						//
  						// allow blocked appends to continue
  						buffer.notifyAll();
  					}
  				}
  
  				//
  				// process events after lock on buffer is released.
  				//
  				if (events != null) {
  					for (int i = 0; i < events.length; i++) {
  						synchronized (appenders) {
  							LoggingEvent event = events[i];											
  							@SuppressWarnings("unchecked")
  							Enumeration<Appender> allAppenders = appenders.getAllAppenders();
  							
  							while (allAppenders.hasMoreElements()) {
  								Appender appender = allAppenders.nextElement();
  
  								//since we may update the appender layout we must sync so other threads won't use it by mistake
  								synchronized (appender) {
  									Layout originalLayout = appender.getLayout();
  									boolean appenderUpdated = udpateLayoutIfNeeded(appender, event);
  
  									appender.doAppend(event);
  									if (appenderUpdated) {
  										appender.setLayout(originalLayout);
  									}
  								}
  
  							}																										
  						}
  					}
  				}
  			}
  		} catch (InterruptedException ex) {
  			Thread.currentThread().interrupt();
  		}
  	}