// Path: wasync/src/main/java/org/atmosphere/wasync/Future.java
// public interface Future extends java.util.concurrent.Future<Socket> {
//     /**
//      * Send data to the remote Server.
//      * @param message the message to fire
//      * @return a {@link Future}
//      * @throws java.io.IOException
//      */
//     Future fire(Object message) throws IOException;
//     /**
//      * Mark the future done. If an exception occurred, this method will throw it.
//      * @return a {@link Future}
//      */
//     Future finishOrThrowException() throws IOException;
// 
//     /**
//      * If an exception occurs, the {@link Transport} will set it using this method. An application can also
//      * use that method to interrupt a blocking {@link Socket#open(Request)} operation. This operation
//      * must unlock the current blocked thread.
//      * @param t a {@link IOException}
//      * @return a {@link Future}
//      */
//     Future ioException(IOException t);
// 
//     /**
//      * Mark this instance as done.
//      */
//     void done();
// 
//     /**
//      * Close the underlying {@link Socket}
//      */
//     void close();
// }
// 
// Path: wasync/src/main/java/org/atmosphere/wasync/Socket.java
// public interface Socket {
// 
//     /**
//      * The current state of the underlying Socket.
//      */
//     public enum STATUS {
//         /**
//          * The socket is not yet connected
//          */
//         INIT,
//         /**
//          * The socket is open and ready to send messages
//          */
//         OPEN,
//         /**
//          * The socket was closed and re-opened
//          */
//         REOPENED,
//         /**
//          * The socket is close
//          */
//         CLOSE,
//         /**
//          * The socket is broken
//          */
//         ERROR }
// 
//     /**
//      * Send data to the remote Server. The object will first be delivered to the set of {@link Encoder}, and then send to the server.
//      * The server's response will be delivered to the set of defined {@link Function} using the opened {@link Transport}, e.g for
//      * {@link Request.TRANSPORT#WEBSOCKET}, the same connection will be re-used and, for others transports, the suspended connection.
//      * @param data object to send
//      * @return a {@link Future}
//      * @throws IOException
//      */
//     Future fire(Object data) throws IOException;
// 
//     /**
//      * Associate a {@link Function} with the Socket. When a response is received, the library will try to associated
//      * the decoded message (decoded by {@link Decoder}) to the defined type of the {@link Function}
//      * @param function a {@link Function}
//      * @return this
//      */
//     Socket on(Function<?> function);
// 
//     /**
//      * Associate a {@link Function} with the Socket. When a response is received, the library will try to associated
//      * the decoded message (decoded by {@link Decoder}) to the defined type of the {@link Function}. The default messages
//      * are defined by {@link org.atmosphere.wasync.Event} but handling of custom message can be done using a {@link FunctionResolver}
//      * @param function a {@link Function}
//      * @return this
//      */
//     Socket on(String functionMessage, Function<?> function);
// 
//     /**
//      * Associate a {@link Function} with an {@link Event}. When the event happen the library will try to associated
//      * the decoded event (decoded by {@link Decoder}) to the defined type of the {@link Function}. The default event
//      * are defined by {@link org.atmosphere.wasync.Event} but handling of custom event can be done using a {@link FunctionResolver}
//      * @param function a {@link Function}
//      * @return this
//      */
//     Socket on(Event event, Function<?> function);
// 
//     /**
//      * Connect to the remote Server using the {@link Request}'s information.
//      * @param request a {@link Request}
//      * @return this
//      * @throws IOException in case the connect fails or a network failure occurs.
//      */
//     Socket open(Request request) throws IOException;
//     
//     /**
//      * Connect to the remote Server using the {@link Request}'s information, will timeout if the connection failed to open 
//      * within a certain time.
//      * @param request a {@link Request}
//      * @param timeout the maximum time to wait
//      * @param unit the time unit of the timeout argument
//      * @return this
//      * @throws IOException in case the connect fails or a network failure occurs.
//      */
//     Socket open(Request request, long timeout, TimeUnit unit) throws IOException;
// 
//     /**
//      * Close this Socket, asynchronously.
//      */
//     void close();
// 
//     /**
//      *  Return the {@link STATUS} of this Socket.
//      */
//     STATUS status();
// }


import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.atmosphere.wasync.Future;
import org.atmosphere.wasync.Socket;
        done();
        try {
            if (ioException != null) {
                throw ioException;
            }
        } finally {
            ioException = null;
        }
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Future ioException(IOException t) {
        ioException = t;
        done();
        return this;
    }

    protected void reset(){
        done.set(false);
        latch = new CountDownLatch(1);
    }

    /**
     * {@inheritDoc}
     */
    @Override
// Path: wasync/src/main/java/org/atmosphere/wasync/Future.java
// public interface Future extends java.util.concurrent.Future<Socket> {
//     /**
//      * Send data to the remote Server.
//      * @param message the message to fire
//      * @return a {@link Future}
//      * @throws java.io.IOException
//      */
//     Future fire(Object message) throws IOException;
//     /**
//      * Mark the future done. If an exception occurred, this method will throw it.
//      * @return a {@link Future}
//      */
//     Future finishOrThrowException() throws IOException;
// 
//     /**
//      * If an exception occurs, the {@link Transport} will set it using this method. An application can also
//      * use that method to interrupt a blocking {@link Socket#open(Request)} operation. This operation
//      * must unlock the current blocked thread.
//      * @param t a {@link IOException}
//      * @return a {@link Future}
//      */
//     Future ioException(IOException t);
// 
//     /**
//      * Mark this instance as done.
//      */
//     void done();
// 
//     /**
//      * Close the underlying {@link Socket}
//      */
//     void close();
// }
// 
// Path: wasync/src/main/java/org/atmosphere/wasync/Socket.java
// public interface Socket {
// 
//     /**
//      * The current state of the underlying Socket.
//      */
//     public enum STATUS {
//         /**
//          * The socket is not yet connected
//          */
//         INIT,
//         /**
//          * The socket is open and ready to send messages
//          */
//         OPEN,
//         /**
//          * The socket was closed and re-opened
//          */
//         REOPENED,
//         /**
//          * The socket is close
//          */
//         CLOSE,
//         /**
//          * The socket is broken
//          */
//         ERROR }
// 
//     /**
//      * Send data to the remote Server. The object will first be delivered to the set of {@link Encoder}, and then send to the server.
//      * The server's response will be delivered to the set of defined {@link Function} using the opened {@link Transport}, e.g for
//      * {@link Request.TRANSPORT#WEBSOCKET}, the same connection will be re-used and, for others transports, the suspended connection.
//      * @param data object to send
//      * @return a {@link Future}
//      * @throws IOException
//      */
//     Future fire(Object data) throws IOException;
// 
//     /**
//      * Associate a {@link Function} with the Socket. When a response is received, the library will try to associated
//      * the decoded message (decoded by {@link Decoder}) to the defined type of the {@link Function}
//      * @param function a {@link Function}
//      * @return this
//      */
//     Socket on(Function<?> function);
// 
//     /**
//      * Associate a {@link Function} with the Socket. When a response is received, the library will try to associated
//      * the decoded message (decoded by {@link Decoder}) to the defined type of the {@link Function}. The default messages
//      * are defined by {@link org.atmosphere.wasync.Event} but handling of custom message can be done using a {@link FunctionResolver}
//      * @param function a {@link Function}
//      * @return this
//      */
//     Socket on(String functionMessage, Function<?> function);
// 
//     /**
//      * Associate a {@link Function} with an {@link Event}. When the event happen the library will try to associated
//      * the decoded event (decoded by {@link Decoder}) to the defined type of the {@link Function}. The default event
//      * are defined by {@link org.atmosphere.wasync.Event} but handling of custom event can be done using a {@link FunctionResolver}
//      * @param function a {@link Function}
//      * @return this
//      */
//     Socket on(Event event, Function<?> function);
// 
//     /**
//      * Connect to the remote Server using the {@link Request}'s information.
//      * @param request a {@link Request}
//      * @return this
//      * @throws IOException in case the connect fails or a network failure occurs.
//      */
//     Socket open(Request request) throws IOException;
//     
//     /**
//      * Connect to the remote Server using the {@link Request}'s information, will timeout if the connection failed to open 
//      * within a certain time.
//      * @param request a {@link Request}
//      * @param timeout the maximum time to wait
//      * @param unit the time unit of the timeout argument
//      * @return this
//      * @throws IOException in case the connect fails or a network failure occurs.
//      */
//     Socket open(Request request, long timeout, TimeUnit unit) throws IOException;
// 
//     /**
//      * Close this Socket, asynchronously.
//      */
//     void close();
// 
//     /**
//      *  Return the {@link STATUS} of this Socket.
//      */
//     STATUS status();
// }


// Path: wasync/src/main/java/org/atmosphere/wasync/impl/DefaultFuture.java
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.atmosphere.wasync.Future;
import org.atmosphere.wasync.Socket;

        done();
        try {
            if (ioException != null) {
                throw ioException;
            }
        } finally {
            ioException = null;
        }
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Future ioException(IOException t) {
        ioException = t;
        done();
        return this;
    }

    protected void reset(){
        done.set(false);
        latch = new CountDownLatch(1);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Socket get() throws InterruptedException, ExecutionException {