code: public static <V> PnkyPromise<V> composeAsync(final ThrowingSupplier<PnkyPromise<V>> operation,
        final Executor executor)
    {
      final Pnky<V> pnky = Pnky.create();
  
      executor.execute(new Runnable()
      {
        @Override
        public void run()
        {
          if (pnky.state.compareAndSet(WAITING, RUNNING))
          {
            try
            {
              operation.get().alwaysAccept(new ThrowingBiConsumer<V, Throwable>()
              {
                @Override
                public void accept(final V result, final Throwable error) throws Throwable
                {
                  if (error != null)
                  {
                    pnky.reject(error);
                  }
                  else
                  {
                    pnky.resolve(result);
                  }
                }
              });
            }
            catch (final Throwable e)
            {
              pnky.reject(e);
            }
          }
        }
      });
  
      return pnky;
    }
docs: Creates a new {@link PnkyPromise future} that completes when the future returned by the
  supplied operation completes, executing the operation on the supplied executor. If the
  operation completes normally, the returned future completes with the result of the future
  returned by the function. If the operation throws an exception, the returned future completes
  exceptionally with the thrown exception.
  
  @param operation
  the operation to perform
  @param executor
  the executor to process the operation on
  
  @return a new {@link PnkyPromise future}