code: protected void fireCompletionActions() {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "fireCompletionActions");
          }
          if (this.firstListener != null) {
              ICompletionListener listenerToInvoke = this.firstListener;
              // reset listener so it can't be inadvertently be called on the next request
              this.firstListener = null;
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "invoking callback for channel id: " + this.channel.channelIdentifier);
              }
              invokeCallback(listenerToInvoke, this, this.firstListenerState);
          } else {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "no listener found for event, future: " + this);
              }
          }
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.exit(tc, "fireCompletionActions");
          }
      }
docs: Impl Assumes we are holding the completed sem lock