    //------------------------------------------------------------------------------
    // emSignal.h
    //
    // Copyright (C) 2005-2008,2010 Oliver Hamann.
    //
    // Homepage: http://eaglemode.sourceforge.net/
    //
    // This program is free software: you can redistribute it and/or modify it under
    // the terms of the GNU General Public License version 3 as published by the
    // Free Software Foundation.
    //
    // This program is distributed in the hope that it will be useful, but WITHOUT
    // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
    // more details.
    //
    // You should have received a copy of the GNU General Public License version 3
    // along with this program. If not, see <http://www.gnu.org/licenses/>.
    //------------------------------------------------------------------------------

    #ifndef emSignal_h
    #define emSignal_h

    #ifndef emScheduler_h
    #include <emCore/emScheduler.h>
    #endif

    //==============================================================================
    //================================== emSignal ==================================
    //==============================================================================

    class emSignal : public emUncopyable {

    public:

            // Class for a signal which can be sent (signaled) to all the engines
            // of an emScheduler.

            emSignal();
            ~emSignal();

            void Signal(emScheduler & scheduler);
                    // Signal this signal. Please even read the comments on
                    // emEngine::AddWakeUpSignal, emEngine::Signal and
                    // emEngine::IsSignaled.

            bool IsPending() const;
                    // If a signal is signaled, it is always pending until the end
                    // or beginning of the schedulers call to an emEngine::Cycle.

            void Abort();
                    // Abort any signaling of this signal. No engine will see this
                    // signal signaled before it is signaled again (but engines
                    // could already have been woken up, except this is called in
                    // the pending phase of the signal).

    private:

            friend class emScheduler;
            friend class emEngine;

            struct Link {
                    emEngine * Engine;
                    Link * * ELThisPtr;
                    Link * ELNext;
                    emSignal * Signal;
                    Link * * SLThisPtr;
                    Link * SLNext;
                    unsigned int RefCount;
            };

            emScheduler::SignalRingNode RNode;
                    // Node for the list of pending signals (emScheduler::PSList).

            Link * ELFirst;
                    // First element in the list of connected engines.

            emUInt64 Clock;
                    // State of emScheduler::Clock after signaling this signal,
                    // modified at end of pending phase.
    };

    inline void emSignal::Signal(emScheduler & scheduler)
    {
            if (!RNode.Next) {
                    RNode.Next=scheduler.PSList.Next;
                    scheduler.PSList.Next=&RNode;
            }
    }

    inline bool emSignal::IsPending() const
    {
            return RNode.Next!=NULL;
    }

    #endif