    // Copyright (C) 2003  Davis E. King (davis@dlib.net)
    // License: Boost Software License   See LICENSE.txt for the full license.
    #undef DLIB_LINKER_KERNEl_ABSTRACT_
    #ifdef DLIB_LINKER_KERNEl_ABSTRACT_

    #include "../threads/threads_kernel_abstract.h"
    #include "../sockets/sockets_kernel_abstract.h"

    namespace dlib
    {

        class linker
        {

            /*!
                INITIAL VALUE
                    is_running() == false

                WHAT THIS OBJECT REPRESENTS
                    This object represents something that takes two connections and lets
                    them talk to each other.  i.e. any incoming data from one connection is
                    passed unaltered to the other and vice versa.

                    note that linker objects are not swappable.

                    Also note that when one connection is closed shutdown_outgoing()
                    is called on the other to signal that no more data will be sent
                    in that direction on the connection.
                    (i.e. the FIN packet is effectively also forwarded by the linker object)

                THREAD SAFETY
                    all member functions are thread-safe.

            !*/

            public:

                linker(
                );
                /*!
                    ensures
                        - #*this is properly initialized
                    throws
                        - std::bad_alloc
                        - dlib::thread_error
                !*/

                linker (
                    connection& a,
                    connection& b
                );
                /*!
                    ensures
                        - #*this is properly initialized
                        - immediately invokes link(a,b);
                          (i.e. using this constructor is the same as creating a linker with
                          the default constructor and then immediately invoking link() on it)
                    throws
                        - std::bad_alloc
                        - dlib::thread_error
                !*/

                virtual ~linker(
                );
                /*!
                    ensures
                        - all resources associated with *this have been released
                !*/

                void clear(
                );
                /*!
                    ensures
                        - #*this has its initial value
                        - if (is_running()) then
                            - the two connections being linked will be shutdown()
                    throws
                        - std::bad_alloc
                            if this exception is thrown then the linker object is unusable
                            until clear() is called and succeeds and
                            if is_running() then the connections will STILL be shutdown()
                            even though an exception is being thrown
                !*/

                bool is_running(
                ) const;
                /*!
                    ensures
                        - returns true if link() is running else
                        - returns false if link() is not running or has released all its
                          resources and is about to terminate
                    throws
                        - std::bad_alloc
                !*/

                void link (
                    connection& a,
                    connection& b
                );
                /*!
                    requires
                        - is_running() == false
                    ensures
                        - all incoming data from connection a will be forwarded to b
                        - all incoming data from connection b will be forwarded to a
                        - #a and #b will have been shutdown()
                        - link() will block until both of the connections have ended
                          or an error occurs
                    throws
                        - std::bad_alloc
                            link() may throw this exception and if it does then the object
                            will be unusable until clear() is called and succeeds and
                            connections a and b will be shutdown()
                        - dlib::socket_error
                            link() will throw a this exception if one of the connections
                            returns an error value (being shutdown is not an error).
                            If this happens then the linker object will be cleared and
                            have its initial value.  note that if this happens then the
                            connections being linked will be shutdown()
                        - dlib::thread_error
                            link() will throw a this exception if there is a problem
                            creating new threads.  Or it may throw this exception if there
                            is a problem creating threading objects. If this happens
                            then the linker object will be cleared and have its initial value.
                            note that if this happens then the connections being linked will
                            be shutdown().
                !*/

            private:

                // restricted functions
                linker(linker&);        // copy constructor
                linker& operator=(linker&);    // assignment operator
        };

    }

    #endif // DLIB_LINKER_KERNEl_ABSTRACT_