code: public BufferOrEvent getNextBufferOrEvent() throws IOException {
  		// return pending events first
  		if (this.pendingEvents != null) {
  			// if the field is not null, it must always have a next value!
  			BufferOrEvent next = new BufferOrEvent(this.pendingEvents.next());
  			if (!this.pendingEvents.hasNext()) {
  				this.pendingEvents = null;
  			}
  			return next;
  		}
  
  		// if no events are pending, get the next buffer
  		Envelope nextEnvelope;
  		synchronized (this.queuedEnvelopes) {
  			if (this.queuedEnvelopes.isEmpty()) {
  				return null;
  			}
  			nextEnvelope = this.queuedEnvelopes.poll();
  		}
  
  		// schedule events as pending, because events come always after the buffer!
  		List<AbstractEvent> events = (List<AbstractEvent>) nextEnvelope.deserializeEvents();
  		Iterator<AbstractEvent> eventsIt = events.iterator();
  		if (eventsIt.hasNext()) {
  			this.pendingEvents = eventsIt;
  		}
  
  		// get the buffer, if there is one
  		if (nextEnvelope.getBuffer() != null) {
  			return new BufferOrEvent(nextEnvelope.getBuffer());
  		}
  		else if (this.pendingEvents != null) {
  			// if the field is not null, it must always have a next value!
  			BufferOrEvent next = new BufferOrEvent(this.pendingEvents.next());
  			if (!this.pendingEvents.hasNext()) {
  				this.pendingEvents = null;
  			}
  
  			return next;
  		}
  		else {
  			// no buffer and no events, this should be an error
  			throw new IOException("Received an envelope with neither data nor events.");
  		}
  	}
docs: ChannelBroker