//------------------------------------------------------------------------------
// emScheduler.h
//
// Copyright (C) 2005-2008 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 emScheduler_h
#define emScheduler_h
#ifndef emStd2_h
#include <emCore/emStd2.h>
#endif
class emEngine;
//==============================================================================
//================================ emScheduler =================================
//==============================================================================
class emScheduler : public emUncopyable {
public:
// Abstract base class for a scheduler on emEngine objects.
emScheduler();
virtual ~emScheduler();
virtual int Run() = 0;
// Do all the time slices until InitiateTermination() is called.
virtual bool IsTimeSliceAtEnd() const = 0;
// See emEngine::IsTimeSliceAtEnd().
virtual void InitiateTermination(int returnCode) = 0;
// Tell the scheduler to terminate round about after the current
// time slice.
emUInt64 GetTimeSliceCounter() const;
// This is incremented by one on each time slice.
protected:
void DoTimeSlice();
// This has to be called by the derived class on each time
// slice. It performs all the scheduling for one time slice, but
// it does not wait for IsTimeSliceAtEnd.
private:
friend class emSignal;
friend class emEngine;
friend class emTimer;
struct SignalRingNode {
// Node for a circular single-linked list of pending signals.
SignalRingNode * Next;
};
struct EngineRingNode {
// Node for a circular double-linked list of awake engines.
EngineRingNode * Prev;
EngineRingNode * Next;
};
SignalRingNode PSList;
// Circular single-linked list of pending signals. The order is
// reversed before processing.
EngineRingNode AwakeLists[10];
// Circular double-linked lists of awake engines. Index is:
// Priority*2+TimeSlice
EngineRingNode * CurrentAwakeList;
// The list currently processed for calling the engines.
emEngine * CurrentEngine;
// The engine currently called, or NULL.
emUInt32 EngineCount;
// Total number of engines.
emInt8 TimeSlice;
// Whether the current time slice is even (0) or odd (1).
emUInt64 Clock;
// Incremented on each loop-run of handling pending signals and
// calling emEngine::Cycle.
emUInt64 TimeSliceCounter;
// Incremented on each time slice.
void * TimerStuff;
// A little hack for the implementation of emTimer.
};
inline emUInt64 emScheduler::GetTimeSliceCounter() const
{
return TimeSliceCounter;
}
//==============================================================================
//============================ emStandardScheduler =============================
//==============================================================================
class emStandardScheduler : public emScheduler {
public:
// Class for a standard scheduler. It tries to make the time slices 10
// millisecs long, but IsTimeSliceAtEnd() allows to have 50 millisecs
// per time slice (for reducing the graphics frame rate when busy).
emStandardScheduler();
virtual int Run();
virtual bool IsTimeSliceAtEnd() const;
virtual void InitiateTermination(int returnCode);
private:
bool TerminationInitiated;
int ReturnCode;
emUInt64 SyncTime, DeadlineTime;
};
#endif