@Override
  public void syn(SynInfo synInfo, StreamFrameListener listener, Promise<Stream> promise) {
    // Synchronization is necessary.
    // SPEC v3, 2.3.1 requires that the stream creation be monotonically crescent
    // so we cannot allow thread1 to create stream1 and thread2 create stream3 and
    // have stream3 hit the network before stream1, not only to comply with the spec
    // but also because the compression context for the headers would be wrong, as the
    // frame with a compression history will come before the first compressed frame.
    int associatedStreamId = 0;
    if (synInfo instanceof PushSynInfo)
      associatedStreamId = ((PushSynInfo) synInfo).getAssociatedStreamId();

    synchronized (this) {
      int streamId = streamIds.getAndAdd(2);
      // TODO: for SPDYv3 we need to support the "slot" argument
      SynStreamFrame synStream =
          new SynStreamFrame(
              version,
              synInfo.getFlags(),
              streamId,
              associatedStreamId,
              synInfo.getPriority(),
              (short) 0,
              synInfo.getHeaders());
      IStream stream = createStream(synStream, listener, true, promise);
      if (stream == null) return;
      generateAndEnqueueControlFrame(
          stream, synStream, synInfo.getTimeout(), synInfo.getUnit(), stream);
    }
    flush();
  }
 @Override
 public Stream syn(SynInfo synInfo, StreamFrameListener listener)
     throws ExecutionException, InterruptedException, TimeoutException {
   FuturePromise<Stream> result = new FuturePromise<>();
   syn(synInfo, listener, result);
   if (synInfo.getTimeout() > 0) return result.get(synInfo.getTimeout(), synInfo.getUnit());
   else return result.get();
 }