001    // MemoryParameters.java, created by wbeebee
002    // Copyright (C) 2001 Wes Beebee <wbeebee@mit.edu>
003    // Licensed under the terms of the GNU GPL; see COPYING for details.
004    package javax.realtime;
005    
006    import java.util.LinkedList;
007    import java.util.Iterator;
008    
009    /**
010     * @author Wes Beebee <<a href="mailto:wbeebee@mit.edu">wbeebee@mit.edu</a>>
011     */
012    
013    /** Memory parameters can be given on the constructor of
014     *  <code>RealtimeThread</code> and <code>AsyncEventHandler</code>. These
015     *  can be used both for the purposes of admission control by the
016     *  scheduler and for the purposes of pacing the garbage collector to
017     *  satisfy all of the thread allocation rates.
018     *  <p>
019     *  When a reference to a <code>MemoryParameters</code> object is given
020     *  as a parameter to a constructor, the <code>MemoryParameters</code>
021     *  object becomes bound to the object being created. Changes to the
022     *  values in the <code>MemoryParameters</code> object affect the
023     *  constructed object. If given to more than one constructor, then
024     *  changes to the values in the <code>MemoryParameters</code> object
025     *  affect <i>all</i> of the associated objects. Note that this is a
026     *  one-to-many relationship and <i>not</i> a many-to-many.
027     *  <p>
028     *  <b>Caution:</b> This class is explicitly unsafe in multithreaded
029     *  situations when it is being changed. No synchronization is done. It
030     *  is assumed that users of this class who are mutating instances will
031     *  be doing their own synchronization at a higher level.
032     */
033    public class MemoryParameters {
034    
035        /** Specifies no maximum limit */
036        public static final long NO_MAX = -1;
037        private long allocationRate;
038        private long maxImmortal;
039        private long maxMemoryArea;
040        private MemoryArea memoryArea;
041    
042        LinkedList schList = new LinkedList();
043    
044        /** Create a <code>MemoryParameters</code> object with the given values.
045         *
046         *  @param maxMemoryArea A limit on the amount of memory the thread may allocate
047         *                       in the memory area. Units are in bytes. If zere, no
048         *                       allocation allowed in the memory area. To specify no
049         *                       limit, use NO_MAX or a value less than zero.
050         *  @param maxImmortal A limit on the amount of memory the thread may allocate
051         *                     in the immortal area. Units are in bytes. If zero, no
052         *                     allocation allowed in immortal memory. To specify no
053         *                     limit, use NO_MAX or a value less than zero
054         *  @throws java.langIllegalArgumentException
055         */
056        public MemoryParameters(long maxMemoryArea, long maxImmortal) 
057            throws IllegalArgumentException {
058            this.maxMemoryArea = Math.max(maxMemoryArea, NO_MAX);
059            this.maxImmortal = Math.max(maxImmortal, NO_MAX);
060            this.allocationRate = NO_MAX;
061        }
062    
063        /** Create a <code>MemoryParameters</code> object with the given values.
064         *
065         *  @param maxMemoryArea A limit on the amount of memory the thread may allocate
066         *                       in the memory area. Units are in bytes. If zere, no
067         *                       allocation allowed in the memory area. To specify no
068         *                       limit, use NO_MAX or a value less than zero.
069         *  @param maxImmortal A limit on the amount of memory the thread may allocate
070         *                     in the immortal area. Units are in bytes. If zero, no
071         *                     allocation allowed in immortal memory. To specify no
072         *                     limit, use NO_MAX or a value less than zero
073         *  @param allocationRate A limit on the rate of allocation in the heap. Units are
074         *                        in bytes per second. If zero, no allocation is allowed
075         *                        in the heap. To specify no limit, use NO_MAX or a value
076         *                        less than zero.
077         *  @throws java.langIllegalArgumentException
078         */
079        public MemoryParameters(long maxMemoryArea, long maxImmortal, 
080                                long allocationRate) 
081            throws IllegalArgumentException {
082            this.maxMemoryArea = Math.max(maxMemoryArea, NO_MAX);
083            this.maxImmortal = Math.max(maxImmortal, NO_MAX);
084            this.allocationRate = Math.max(allocationRate, NO_MAX);
085        }
086    
087        public MemoryParameters(MemoryArea memoryArea) {
088            this.memoryArea = memoryArea;
089        }
090    
091        /** Gets the allocation rate. Units are in bytes per second.
092         *
093         *  @return The allocation in bytes per second.
094         */
095        public long getAllocationRate() {
096            return allocationRate;
097        }
098    
099        /** Gets the limit on the amount of memory the thread may allocate
100         *  in the immortal area. Units are in bytes.
101         *
102         *  @return The limit of immortal memory.
103         */
104        public long getMaxImmortal() {
105            return maxImmortal;
106        }
107    
108        /** Gets the limit on the amount of memory the thread may allocate
109         *  in the memory area. Units are in bytes.
110         *
111         *  @return The allocation limit in this area.
112         */
113        public long getMaxMemoryArea() {
114            return maxMemoryArea;
115        }
116    
117        /** Sets the limit on the rate of allocation in the heap.
118         *
119         *  @param allocationRate Units are in bytes per second. If zero, no
120         *                        allocation is allowed in the heap. To specify
121         *                        no limit, use NO_MAX or a values less than zero.
122         */
123        public void setAllocationRate(long rate) {
124            allocationRate = Math.max(rate, NO_MAX);
125        }
126    
127        /** Sets the limit on the rate of allocation in the heap. If this
128         *  <code>MemoryParameters</code> object is currently associated with
129         *  one or more realtime threads that have been passed admission
130         *  control, this change in allocation rate will be submitted to
131         *  admission control. The scheduler (in conjuction with the garbage
132         *  collector) will either admit all the affected threads with the new
133         *  allocation rate, or leave the allocation rate unchanged and cause
134         *  <code>setAllocationRateIfFeasible</code> to return <code>false</code>.
135         *
136         *  @param allocationRate Units are in bytes per second. If zero, no
137         *                        allocation is allowed in the heap. To specify
138         *                        no limit, use NO_MAX or a value less than zero.
139         *  @return True, if the request was fulfilled.
140         */
141        public boolean setAllocationRateIfFeasible(int allocationRate) {
142            // How do memory parameters affect the feasibility of the task set?
143            setAllocationRate(allocationRate);
144            for (Iterator it = schList.iterator(); it.hasNext(); )
145                ((Schedulable)it.next()).setMemoryParameters(this);
146    
147            return true;
148        }
149        
150        /** Sets the limit on the amount of memory the thread may allocate in the immortal area.
151         *
152         *  @param maximum Units are in bytes. If zero, no allocation allowed in
153         *                 immortal. To specify no limit, use NO_MAX or a value
154         *                 less than zero.
155         *  @return True if the value is set. False if any of the threads have
156         *          already allocated more than the given value. in this case
157         *          the call has no effect.
158         */
159        public boolean setMaxImmortalIfFeasible(long maximum) {
160            // How do memory parameters affect the feasibility of the task set?
161            setMaxImmortal(maximum);
162            for (Iterator it = schList.iterator(); it.hasNext(); )
163                ((Schedulable)it.next()).setMemoryParameters(this);
164    
165            return true;
166        }
167    
168        /** Sets the limit on the amount of memory the thread may allocate in the memory area.
169         *
170         *  @param maximum Units are in bytes. If zero, no allocation allowed in
171         *                 the memory area. To specify no limit, use NO_MAX or a
172         *                 value less than zero.
173         *  @return True if the value is set. False if any of the threads have already
174         *          allocated more than the given value. In this case the call has no effect.
175         */
176        public boolean setMaxMemoryAreaIfFeasible(long maximum) {
177            // How do memory parameters affect the feasibility of the task set?
178            setMaxMemoryArea(maximum);
179            for (Iterator it = schList.iterator(); it.hasNext(); )
180                ((Schedulable)it.next()).setMemoryParameters(this);
181    
182            return true;
183        }
184    
185        public /* private ? */ void setMaxImmortal(long maximum) {
186            maxImmortal = maximum;
187        }
188    
189        public /* private ? */ void setMaxMemoryArea(long maximum) {
190            maxMemoryArea = maximum;
191        }
192    
193        public MemoryArea getMemoryArea() {
194            return memoryArea;
195        }
196    
197        /** Informs <code>this</code> that there is one more instance of <code>Schedulable</code>
198         *  that uses <code>this</code> as its <code>ReleaseParameters</code>.
199         */
200        public boolean bindSchedulable(Schedulable sch) {
201            return schList.add(sch);
202        }
203    
204        /** Informs <code>this</code> that <code>Schedulable sch</code>
205         *  that uses <code>this</code> as its <code>ReleaseParameters</code>.
206         */
207        public boolean unbindSchedulable(Schedulable sch) {
208            return schList.remove(sch);
209        }    
210    }