001    // PeriodicParameters.java, created by cata
002    // Copyright (C) 2001 Catalin Francu <cata@mit.edu>
003    // Licensed under the terms of the GNU GPL; see COPYING for details.
004    
005    package javax.realtime;
006    
007    import java.util.Date;
008    import java.util.LinkedList;
009    import java.util.Iterator;
010    
011    /** This release parameter indicates that the <code>waitForNextPeriod()</code>
012     *  method on the associated <code>Schedulable</code> object will be unblocked
013     *  at the start of each period. When a reference to a
014     *  <code>PeriodicParameters</code> object is given as a parameter to a
015     *  constructor, the <code>PeriodicParameters</code> object becomes bound to
016     *  the object being created. Changes to the values in the
017     *  <code>PeriodicParameters</code> object affect the constructed object. If
018     *  given to more than one constructor then changes to the values in the
019     *  <code>PeriodicParameters</code> object affect <i>all</i> the associated objects.
020     *  Note that this is a one-to-many relationship, <i>not</i> many-to-many.
021     *  <p>
022     *  <b>Caution:</b> This class is explicitly unsafe in multithreaded situations
023     *  when it is being changed. No synchronizations is done. It is assumed that users
024     *  of this class who are mutating instances will be doing their own synchronization
025     *  at a higher level.
026     */
027    public class PeriodicParameters extends ReleaseParameters {
028        
029        HighResolutionTime start;
030        RelativeTime period;
031        LinkedList schList = new LinkedList();
032    
033        /** Create a <code>PeriodicParameters</code> object.
034         *
035         *  @param start Time at which the first period begins. If a
036         *               <code>RelativeTime</code>, this time is relative to the
037         *               first time the schedulable object becomes schedulable
038         *               (<i>schedulable time</i>) (e.g., when <code>start()</code>
039         *               is called on a thread). If an <code>AbsoluteTime</code>
040         *               and it is before the schedulable time, start is equivalent
041         *               to the schedulable time.
042         *  @param period The period is the interval between successive unblocks
043         *                of <code>RealtimeThread.waitForNextPeriod()</code>. Must
044         *                be greater than zero when entering feasibility analysis.
045         *  @param cost Processing time per period. On implementations which can
046         *              measure the amount of time a schedulable object is executed,
047         *              this value is the maximum amount of time a schedulable object
048         *              receives per period. On implementations which cannot measure
049         *              execution time, this value is used as a hint to the feasibility
050         *              algorithm. On such systems it is not possible to determine when
051         *              any particular object exceeds or will exceed cost time units in
052         *              a period. Equivalent to <code>RelativeTime(0, 0)</code> if null.
053         *  @param deadline The latest permissible completion time measured from the
054         *                  release time of the associated invocation of the schedulable
055         *                  object. For a minimum implementation for purposes of 
056         *                  feasibility analysis, the deadline is equal to the period.
057         *                  Other implementations may use this parameter to compute
058         *                  execution eligibility. If null, deadline will equal the period.
059         *  @param overrunHandler This handler is invoked if an invocation of the
060         *                        schedulable object exceeds cost in the given period.
061         *                        Not required for minimum implementation. If null,
062         *                        nothing happens on the overrun condition.
063         *  @param missHandler This handler is invoked if the <code>run()</code> method of
064         *                     the schedulable object is still executing after the deadline
065         *                     has passed. Although minimum implementations do not consider
066         *                     deadlines in feasibility calculations, they must recognize
067         *                     variable deadlines and invoke the miss handler as appropriate.
068         *                     If null, nothing happens on the miss deadline condition.
069         */
070        public PeriodicParameters(HighResolutionTime start, RelativeTime period,
071                                  RelativeTime cost, RelativeTime deadline,
072                                  AsyncEventHandler overrunHandler,
073                                  AsyncEventHandler missHandler) {
074            super(cost, (deadline == null) ? period : deadline,
075                  overrunHandler, missHandler);
076            
077            // For now, we leave start as it is. When start() is called on a thread,
078            // then we will set start accordingly. The problem is what do we do when
079            // several threads share the same ReleaseParameters.
080            this.start = start;
081            this.period = new RelativeTime(period);
082        }
083    
084        /** Gets the period.
085         *
086         *  @return The current value in <code>period</code>.
087         */
088        public RelativeTime getPeriod() {
089            return period;
090        }
091    
092        /** Gets the start time.
093         *
094         *  @return The current value in <code>start</code>.
095         */
096        public HighResolutionTime getStart() {
097            return start;
098        }
099    
100        /** This method appears in many classes in the RTSJ and with various parameters.
101         *  The parameters are either new scheduling characteristics for an instance
102         *  <code>Schedulable</code> or an instance of <code>Schedulable</code>. The
103         *  method first performs a feasibility analysis using the new scheduling
104         *  characteristics as replacements for the matching scheduling characteristics
105         *  of either <code>this</code> or the given instance of <code>Schedulable</code>.
106         *  If the resulting system is feasible the method replaces the current scheduling
107         *  characteristics, of either <code>this</code> or the given instance of
108         *  <code>Schedulable</code> as appropriate, with the new scheduling characteristics.
109         *
110         *  @param period The proposed period.
111         *  @param cost The proposed cost.
112         *  @param deadline The proposed deadline.
113         *  @return True, if the resulting system is feasible and the changes are made.
114         *          False, if the resulting system is not feasible and no changes are made.
115         */
116        public boolean setIfFeasible(RelativeTime period,
117                                     RelativeTime cost,
118                                     RelativeTime deadline) {
119            boolean b = true;
120            for (Iterator it = schList.iterator(); it.hasNext(); ) {
121                Schedulable sch = (Schedulable)it.next();
122                Scheduler sched = sch.getScheduler();
123                if (!sched.isFeasible(sch, new PeriodicParameters(getStart(), period, cost, deadline,
124                                                                  overrunHandler, missHandler))) {
125                    b = false;
126                    break;
127                }
128            }
129    
130            if (b) {
131                setPeriod(period);
132                setCost(cost);
133                setDeadline(deadline);
134            }
135            return b;
136        }
137    
138        /** Sets the period.
139         *
140         *  @param period The value to which <code>period</code> is set.
141         */
142        public void setPeriod(RelativeTime period) {
143            this.period.set(period);
144        }
145    
146        /** Sets the start time.
147         *
148         *  @param start The value to which <code>start</code> is set.
149         */
150        public void setStart(HighResolutionTime start) {
151            this.start.set(start);
152        }
153    
154        /** Informs <code>this</code> that there is one more instance of <code>Schedulable</code>
155         *  that uses <code>this</code> as its <code>ReleaseParameters</code>.
156         */
157        public boolean bindSchedulable(Schedulable sch) {
158            return schList.add(sch);
159        }
160    
161        /** Informs <code>this</code> that <code>Schedulable sch</code>
162         *  that uses <code>this</code> as its <code>ReleaseParameters</code>.
163         */
164        public boolean unbindSchedulable(Schedulable sch) {
165            return schList.remove(sch);
166        }
167    }