Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: desmoj/Bin.java


1   package desmoj;
2   
3   /**
4    * Bin is the place where producers can store their products for consumers 
5    * to come and use them up.
6    * Bin is used to implement process synchronization between producers and
7    * consumers. Producers are producing products and store them using 
8    * <code>store()</code> in the bin. Consumers make the Bin 
9    * <code>deliver()</code> the products to use them up.
10   * If no or not enough units of a product are available for the consumers,
11   * they have to wait in a queue until new units are delivered by a
12   * producer.
13   * The first sort criteria of the queue is always highest priorities first,  
14   * the second queueing discipline of the underlying queue and the capacity  
15   * limit can be determined by the user (default is Fifo and unlimited 
16   * capacity).
17   * Bin is derived from QueueBased, which provides all the statistical 
18   * functionality for a queue. 
19   * @see QueueBased
20   *  
21   * @author Soenke Claassen
22   * @author based on DESMO-C from Thomas Schniewind, 1998
23   * 
24   * @version DESMO-J,  Ver. 1.5 copyright (c) 2001 licensed under GNU GPL
25   */
26   
27  public class Bin extends desmoj.QueueBased
28  {
29    
30  //   ******   attributes   ******
31  
32    /**
33    * The queue, actually storing the processes waiting for products
34    */
35    private QueueList  queue;
36    
37    /**
38    * The initial number of products in the Bin
39    */
40    private long   initial;
41    
42    /**
43    * The maximum number of products in the Bin
44    */ 
45    private long   maximum;
46    
47    /**
48    * Number of products available at the moment
49    */ 
50    private long   avail;
51    
52    /**
53    * Number of producers having visited the Bin
54    */ 
55    private long   producers;  
56    
57    /**
58    * Number of consumers having visited the Bin
59    */
60    private long   consumers;
61    
62    /**
63    * Weighted sum of available products in the Bin over the time
64    * (must be divided by the total time to get the average available units!)
65    */
66    private double   wSumAvail;
67    
68    /**
69    * The last time the Bin has been used
70    */
71    private SimTime lastUsage;
72    
73    /**
74    * Indicates the method where something has gone wrong. Is passed as a 
75    * parameter to the method <code>checkProcess()</code>.
76    */
77    private String where;
78    
79   /**
80    * Counter for the SimProcesses which are refused to be enqueued, because the
81    * queue capacity is full.
82    */
83    private long refused;  
84  
85   /**
86    * Flag to indicate whether an entity can pass by other entities in the queue
87    * which are enqueued before that entity in the queue. Is <code>false</code> per
88    * default.
89    */
90    private boolean passBy = false;  
91    
92  //   ******   methods   ****** 
93      
94  /**
95   * Constructor for a Bin with a number of initial units of a product in it.
96   * The queueing discipline and the capacity limit of the underlying queue
97   * can be chosen, too. Highest priority are always first in the queue.
98   * @param owner Model : The model this Bin is associated to.
99   * @param name java.lang.String : The Bin's name
100  * @param sortOrder int : determines the sort order of the underlying 
101  * queue implementation. Choose a constant from <code>QueueBased</code>
102  * like <code>QueueBased.FIFO</code> or <code>QueueBased.LIFO</code> or ...
103  * @param qCapacity int : The capacity of the queue, that is how many
104  * processes can be enqueued. Zero (0) means unlimited capacity.
105  * @param initialUnits long : The units of a product the Bin starts with.
106  * Must be positive.
107  * @param showInReport boolean : Flag, if Bin should produce a report or not.
108  * @param showInTrace boolean : Flag for trace to produce trace messages.
109  */
110   public Bin (desmoj.Model owner, String name, int sortOrder, int qCapacity,
111                 long initialUnits, boolean showInReport, boolean showInTrace)
112   {
113     super (owner, name, showInReport, showInTrace);    // construct QueueBased 
114     reset();                                          
115     
116     this.initial = initialUnits;
117     this.maximum = initialUnits;
118     this.avail = initialUnits;
119     
120     if (initialUnits < 0)    // there can't be less than nothing
121     {
122       sendWarning ( "Attempt to construct a Bin with a negativ number of"+ 
123         " units. Initial number of units set to zero!",
124         "Bin: " + getName() + " Constructor: Bin (desmoj.Model owner, " + 
125         "String name, long initialUnits, boolean showInReport, " +
126         "boolean showInTrace)",
127         "A negative number of units does not make sense here.",
128         "Make sure to initialize a Bin always with a positive number of "+
129         "initialUnits."); 
130       
131       initial = maximum = avail = 0;  // set it to 0, that makes more sense
132     }
133 
134     // check if a valid sortOrder is given
135     if ( sortOrder < 0 )  {
136       sendWarning ( "The given sortOrder parameter is negative! " +
137                     "A queue with Fifo sort order will be created.",
138                     "Bin : "+getName()+
139                     " Constructor: Bin (desmoj.Model owner, String name, "+
140                     "int sortOrder, long qCapacity, long initialUnits, " +
141                     "boolean showInReport, boolean showInTrace)",
142                     "A valid positive integer number must be provided to " +
143                     "determine the sort order of the underlying queue.",
144                     "Make sure to provide a valid positive integer number "+
145                     "by using the constants in the class QueueBased, like "+
146                     "QueueBased.FIFO or QueueBased.LIFO.");
147       // make a Fifo queue
148       queue = new QueueListFifo();  // better than nothing
149       queue.setQueueBased(this);
150     }
151     else  {
152       try   {
153         // determine the queueing strategy
154         Class queueListStrategy = queueingStrategy[sortOrder];
155 
156         queue = (QueueList)queueListStrategy.newInstance();
157       }
158 
159       catch  ( ArrayIndexOutOfBoundsException arrayExcept)  {
160         // the given sortOrder is not valid
161         sendWarning ( "The given sortOrder parameter is not valid! " +
162                       "A queue with Fifo sort order will be created.",
163                       "Bin : "+getName()+
164                       " Constructor: Bin (desmoj.Model owner, String name, "+
165                       "int sortOrder, long qCapacity, long initialUnits, " +
166                       "boolean showInReport, boolean showInTrace)",
167                       "A valid positive integer number must be provided to " +
168                       "determine the sort order of the underlying queue.",
169                       "Make sure to provide a valid positive integer number "+
170                       "by using the constants in the class QueueBased, like "+
171                       "QueueBased.FIFO or QueueBased.LIFO.");
172         // make a Fifo queue
173         queue = new QueueListFifo();  // better than nothing  
174       }
175 
176       catch  ( IllegalAccessException illAccExcept)  {
177         // the class to be loaded can not be found
178         sendWarning ( "IllegalAccessException: The class implementing the " +
179                       "sortOrder of the queue can not be found. A queue with "+
180                       "Fifo sort order will be created instead.",
181                       "Bin : "+getName()+
182                       " Constructor: Bin (desmoj.Model owner, String name, "+
183                       "int sortOrder, long qCapacity, long initialUnits, " +
184                       "boolean showInReport, boolean showInTrace)",
185                       "Programm error when trying to create an instance of a " +
186                       "class. Maybe the zero-argument constructor of that " +
187                       "class can not be found",
188                       "Make sure to provide a valid positive integer number "+
189                       "for the sort order by using the constants in the class "+
190                       "QueueBased, like QueueBased.FIFO or QueueBased.LIFO. "+
191                       "Contact one of the developers of DESMO-J!");
192         // make a Fifo queue
193         queue = new QueueListFifo();  // better than nothing  
194       }
195     
196       catch  ( InstantiationException instExcept)  {
197         // no object of the given class can be instantiated
198         sendWarning ( "InstantiationException: No object of the given class " +
199                       "can be instantiated! A queue with Fifo sort order will "+
200                       "be created instead.",
201                       "Bin : "+getName()+
202                       " Constructor: Bin (desmoj.Model owner, String name, "+
203                       "int sortOrder, long qCapacity, long initialUnits, " +
204                       "boolean showInReport, boolean showInTrace)",
205                       "Programm error when trying to create an instance of a " +
206                       "class. Maybe the the class is an interface or an " +
207                       "abstract class that can not be instantiated",
208                       "Make sure to provide a valid positive integer number "+
209                       "for the sort order by using the constants in the class "+
210                       "QueueBased, like QueueBased.FIFO or QueueBased.LIFO. "+
211                       "Contact one of the developers of DESMO-J!");
212         // make a Fifo queue
213         queue = new QueueListFifo();  // better than nothing  
214       }
215        
216       // give the QueueList a reference to this QueueBased
217       queue.setQueueBased(this);
218     }
219 
220     // set the capacity of the queue
221     queueLimit = qCapacity;
222 
223     // check if it the capacity does make sense
224     if ( qCapacity < 0 )
225     {
226       sendWarning ( "The given capacity of the queue is negative! " +
227                     "A queue with unlimited capacity will be created instead.",
228                     "Bin : "+getName()+
229                     " Constructor: Bin (desmoj.Model owner, String name, "+
230                     "int sortOrder, long qCapacity, long initialUnits, " +
231                     "boolean showInReport, boolean showInTrace)",
232                     "A negative capacity for a queue does not make sense." ,
233                     "Make sure to provide a valid positive capacity "+
234                     "for the underlying queue.");
235       // set the capacity to the maximum value
236       queueLimit = Integer.MAX_VALUE;
237     }
238 
239     // check if qCapacity is zero (that means unlimited capacity)
240     if ( qCapacity == 0 )
241     {
242       // set the capacity to the maximum value
243       queueLimit = Integer.MAX_VALUE;
244     }
245     
246   }
247 //   ******   methods   ****** 
248     
249 /**
250  * Constructor for a Bin with a number of initial units of a product in it.
251  * The underlying queue has a Fifo queueing discipline and unlimited capacity.
252  * @param owner Model : The model this Bin is associated to.
253  * @param name java.lang.String : The Bin's name
254  * @param initialUnits long : The units of a product the Bin starts with.
255  * Must be positive.
256  * @param showInReport boolean : Flag, if Bin should produce a report or not.
257  * @param showInTrace boolean : Flag for trace to produce trace messages.
258  */
259   public Bin (desmoj.Model owner, String name, long initialUnits,
260                 boolean showInReport, boolean showInTrace)
261   {
262     super (owner, name, showInReport, showInTrace);    // construct QueueBased
263     reset();
264     
265     queue = new QueueListFifo();    // make an actual queue and give it a 
266     queue.setQueueBased(this);      // reference of this "QueueBased"-Bin 
267     
268     this.initial = initialUnits;
269     this.maximum = initialUnits;
270     this.avail = initialUnits;
271     
272     if (initialUnits < 0)    // there can't be less than nothing
273     {
274       sendWarning ( "Attempt to construct a Bin with a negativ number of"+ 
275         " units. Initial number of units set to zero!",
276         "Bin: " + getName() + " Constructor: Bin (desmoj.Model owner, " + 
277         "String name, long initialUnits, boolean showInReport, " +
278         "boolean showInTrace)",
279         "A negative number of units does not make sense here.",
280         "Make sure to initialize a Bin always with a positive number of "+
281         "initialUnits."); 
282       
283       initial = maximum = avail = 0;  // set it to 0, that makes more sense
284     }
285   }
286 /** 
287  * Activates the SimProcess <code>process</code>, given as a parameter of 
288  * this method, as the next process. This process should be a SimProcess 
289  * waiting in the queue for some products. 
290  * @param process SimProcess : The process that is to be activated as next.
291  */
292 protected void activateAsNext ( SimProcess process )  
293 {
294   where = "protected void activateAsNext(SimProcess process)";
295   
296   if ( process != null )
297   {
298     // if the given process is not valid just return
299     if ( ! checkProcess (process, where) )    
300     { return; }                                
301     
302     // if the process is scheduled (on the event list) already
303     if ( process.isScheduled() )
304     {
305       process.skipTraceNote();      // don't tell the user, that we ...
306       process.cancel();              // get the process from the EventList
307     }
308     
309     // remember if the process is blocked at the moment
310     boolean wasBlocked = process.isBlocked();
311     
312     // unblock the process to be able to activate him
313     if (wasBlocked)
314     {
315       process.setBlocked(false);  // the process is not blocked anymore and 
316     }                              // ready to become activated
317       
318     // don't tell the user, that we activate the process after the current process
319     process.skipTraceNote();
320     process.activateAfter (current());  
321 
322     // the process status is still "blocked"
323     if (wasBlocked)
324     {
325       process.setBlocked(true);      
326     }
327   }          // end outer if
328 }
329 /**
330  * Activates the first process waiting in the queue. That is a 
331  * process which was trying to take products, but it could not get any 
332  * because there were not enough products for it or another process was
333  * first in the queue to be served. This method is called every time a 
334  * producer has given new products or a consumer in the waiting queue is 
335  * satisfied. 
336  */
337 protected void activateFirst ()  
338 {
339   where = "protected void activateFirst()";
340   
341   // first is the first process in the queue (or null if none is in the queue)
342   SimProcess first = (SimProcess) queue.first();
343     
344   if ( first != null )
345   {  
346     // if first is not modelcompatible just return
347     if ( !checkProcess (first, where))   
348     { return;}                  
349     
350     // if first is scheduled (on the event list) already
351     if (first.isScheduled())
352     {
353       first.skipTraceNote();    // don't tell the user, that we ...
354       first.cancel();            // get the process from the Eventlist
355     }
356     
357     // remember if first is blocked at the moment
358     boolean wasBlocked = first.isBlocked();
359     
360     // unblock the process to be able to activate him
361     if (wasBlocked)
362     {
363       first.setBlocked(false);  
364     }
365       
366     // don't tell the user, that we activate first after the current process
367     first.skipTraceNote();        
368     first.activateAfter (current());  
369 
370     // the status of first is still "blocked"  
371     if (wasBlocked)
372     {
373       first.setBlocked(true);    
374     }
375   }  // end outer if
376 }
377 /**
378  * Returning the average number of products available in the bin 
379  * over the time since the last reset of the bin.
380  * @return double : The average number of products available in the bin 
381  * over the time since the last reset of the bin.
382  */ 
383   public double avgAvail ()  
384   {  
385     SimTime now = currentTime();  // what is the time?
386     // how long since the last reset
387     double diff = now.getTimeValue() - resetAt().getTimeValue();
388   
389     // update the weighted sum of available units
390     double wSumAvl = wSumAvail + 
391       ((double)avail * (now.getTimeValue() - lastUsage.getTimeValue()));
392     
393     if (diff < epsilon().getTimeValue())  // diff is not long enough
394     {
395       sendWarning ( "A Division-by-Zero error occured in a calculation. " +
396       "The UNDEFINED Value: -1.0 is returned as result." ,
397         "Bin: " + getName() + " Method: double avgAvail ()",
398         "The Time difference is shorter than epsilon.", 
399         "Make sure not to use avgAvail() right after a reset.");
400       return UNDEFINED;    // see QueueBased: UNDEFINED = -1
401     }
402     // return the rounded average
403     return java.lang.Math.rint( 100000 * (wSumAvl/diff) ) / 100000;  
404   }
405 /**
406  * Checks whether the entity using the bin is a valid process.
407  * @return boolean : Returns whether the SimProcess is valid or not.  
408  * @param p SimProcess : Is this SimProcess a valid one?
409  * @param where String : The method having called <code>checkProcess()</code>
410  * as a String.
411  */
412   protected boolean checkProcess (SimProcess p, String where)  
413   {
414     if (p == null)    //if p is a null pointer instead of a process
415     {  
416       sendWarning ( "A non existing process is trying to use a Bin object. " +
417         "The attempted action is ignored!",
418         "Bin: " + getName() + " Method: " + where ,
419         "The process is only a null pointer.", 
420         "Make sure that only real SimProcesses are using Bins." );
421       return false;
422     }
423     
424     if (!isModelCompatible( p ) )  // if p is not modelcompatible
425     {  
426       sendWarning ( "The process trying to use a Bin object does not "+
427         "belong to this model. The attempted action is ignored!" ,
428         "Bin: " + getName() + " Method: " + where ,
429         "The process is not modelcompatible.", 
430         "Make sure that processes are using only Bins within their model.");
431       return false;
432     }
433     
434     return true;
435   }
436 /**
437  * Returns a Reporter to produce a report about this Bin.
438  * @return desmoj.report.Reporter : The Reporter for the queue inside this bin
439  */
440   public desmoj.report.Reporter createReporter() 
441   {
442     return new desmoj.report.BinReporter(this);
443   }
444 /**
445  * Method for consumers to make the Bin deliver a number of n products.
446  * When there are not enough products available or another consumer is first
447  * in the queue to be served (and it is not possible to pass by), the current 
448  * consumer process will be blocked and inserted in the waiting queue.
449  * @return boolean : Is <code>true</code> if the specified number of units 
450  * have been delivered successfully, <code>false</code> otherwise 
451  * (i.e. capacity limit of the queue is reached).
452  * @param n long : The number of products the Bin is delivering to the
453  * consumer.
454  */
455   public boolean deliver (long n)  
456   {  
457     where = "boolean deliver (long n)";
458                                           
459     SimProcess currentProcess = currentSimProcess(); 
460     
461     if (!checkProcess(currentProcess, where))  //check the current process
462     { return false; }                          // if it is not valid return false
463   
464     if (n <= 0)    // if the process is taking nothing or less
465     {
466       sendWarning ( "Attempt to take nothing or a negative number of units"+
467         " out of a Bin. The attempted action is ignored!" ,
468         "Bin: " + getName() + " Method: " + where,
469         "It does not make sense to take nothing or less out of a Bin. " +
470         "The statistic will be corrupted with negative numbers!" , 
471         "Make sure to take at least one unit out of the Bin.");
472       return false;      // go to where you came from; ignore that rubbish
473     }
474 
475     if ( queueLimit <= length() )  // check if capac. limit of queue is reached
476     {
477       sendDebugNote("refuses to insert "+currentProcess.getQuotedName()+
478           " in waiting queue, because the capacity limit is reached. ");
479 
480       sendTraceNote("is refused to be enqueued in "+this.getQuotedName() +
481           "because the capacity limit (" + getQueueLimit() + ") of the " +
482           "queue is reached");
483 
484       refused++;  // count the refused ones
485     
486       return false;  // capacity limit is reached
487     }
488     
489     // insert every process in the queue for statistic reasons
490     queue.insert (currentProcess);  
491                                     
492     // is it possible for this process to pass by?
493     if ( passBy == false )
494     {
495       if ( n > avail ||                     // not enough products available OR
496            currentProcess != queue.first() )  // other process is first in the q
497       {
498         // tell in the trace what the process is waiting for
499         if ( traceIsOn() )
500         {
501           sendTraceNote ( "awaits " + n + " of '" + this.getName() + "'" );  
502         }                
503 
504         // for debugging purposes
505         if ( debugIsOn() )
506         {      
507           sendDebugNote( "can not deliver "+  n + " units for " + 
508                           currentProcess.getQuotedName() + "<br>" +
509                           "because there are only "+ getAvail() + " units " +
510                           "right now.");
511         } 
512           
513         do
514         {                                    // the process is stuck in here
515           currentProcess.setBlocked(true);  // as long as ...see while
516           currentProcess.skipTraceNote();    // don't tell the user, that we ...
517           currentProcess.passivate();        // passivate the current process
518         } 
519         while ( n > avail ||         // not enough products available OR
520                 currentProcess != queue.first() );  // other process is first
521       }    // end if
522       
523     }    // end if (passBy = false)
524     
525     else  // the process can pass by other processes in the queue, passBy = true
526     {
527       if ( n > avail ||                     // not enough products available OR
528            currentProcess != queue.first() )  // other process is first in the q
529       {
530         // if this process is not the first in the queue
531         if ( currentProcess != queue.first() )
532         {
533           // we have to make sure that no other process in front of this current
534           // process in the wait queue could be satisfied, so activate
535           // the first Process in the queue to see what he can do. He will pass
536           // the activation on to his successors until this process will be
537           // activated again to get his products. (hopefully)
538           activateFirst();
539         }
540 
541         // only if not enough units are available the process has to wait
542         if ( n > avail )
543         {
544           // tell in the trace what the process is waiting for
545           if ( traceIsOn() )
546           {
547             sendTraceNote ( "awaits " + n + " of '" + this.getName() + "'" );  
548           }  
549         
550           // for debugging purposes
551           if ( debugIsOn() )
552           {      
553             sendDebugNote( "can not deliver "+  n + " units for " + 
554                             currentProcess.getQuotedName() + "<br>" +
555                             "because there are only "+ getAvail() + " units " +
556                             "right now.");
557           }
558         }    // end if not enough units are available
559         
560         // block and passivate the process until enough products are available
561         do
562         {                                    // the process is stuck in here
563           currentProcess.setBlocked(true);  // as long as ...see while
564           currentProcess.skipTraceNote();    // don't tell the user, that we ...
565           currentProcess.passivate();        // passivate the current process
566 
567           // activate the next process in the queue to see what he can do
568           activateAsNext( (SimProcess)queue.succ(currentProcess) );
569         } 
570         while ( n > avail );  // not enough products available
571       }  
572     }    // end else (passBy = true)
573 
574     // the current process has got the products he wanted ...
575     
576     // tell in the trace what the process is taking from the Bin
577     if ( traceIsOn() )
578     {
579       sendTraceNote ( "takes " + n + " from '" + this.getName() + "'" );
580     }            
581       
582     queue.remove (currentProcess);    // get the process out of the queue
583     currentProcess.setBlocked(false);  //we are not blocked (anymore), yeah!
584       
585     // activate the new first process in the queue
586     activateFirst();
587       
588     updateStatistics ( -n );  // statistics will be updated
589                               // with a negative n for deliver(), remember?!
590     return true;  
591   }
592 /**
593  * Returns the number of units available at the moment.
594  * @return long : The number of units available at the moment.
595  */
596   public long getAvail ()  
597   {
598     return this.avail;
599   }
600 /**
601  * Returns the number of consumers having visited the Bin.
602  * @return long : The number of consumers having visited the bin. 
603  */
604   public long getConsumers ()
605   {
606     return this.consumers;
607   }
608 /**
609  * Returns the initial number of products in the bin.
610  * @return long : The number of products the bin started with. 
611  */
612   public long getInitial ()  
613   {
614     return this.initial;
615   }
616 /**
617  * Returns the maximum number of products in the bin.
618  * @return long : The maximum number of products in the bin.  
619  */
620   public long getMaximum ()  
621   {
622     return this.maximum;
623   }
624 /**
625  * Returns whether entities can pass by other entities which are enqueued before
626  * them in the queue.
627  * @return boolean : Indicates whether entities can pass by other entities which 
628  * are enqueued before them in the queue.
629  */
630 public boolean getPassBy() 
631 {
632   return passBy;
633 }
634 /**
635  * Returns the number of producers having used the Bin.
636  * @return long : The number of producers having put products in the bin. 
637  */
638   public long getProducers ()
639   {
640     return this.producers;
641   }
642 /**
643  * Returns the implemented queueing discipline of the underlying queue 
644  * as a String, so it can be displayed in the report.
645  * @return String : The String indicating the queueing discipline.
646  */
647 public String getQueueStrategy() {
648 
649   return queue.getAbbreviation();    // that's it
650 
651 }
652 /**
653  * Returns the number of entities refused to be enqueued in the queue,
654  * because the capacity limit is reached.
655  * @return long : The number of entities refused to be enqueued in the queue.
656  */
657 public long getRefused() {
658   
659   return refused;  // that's it
660 }
661 /**
662  * To reset the statistics of this bin. The number of available
663  * products at this moment and the processes waiting in the queue are not
664  * changed. But all statistic counters are reset.
665  * The <code>QueueBased</code> is also reset.  
666  */
667   public void reset ()  
668   {  
669     super.reset();    // reset the QueueBased also
670     
671     maximum = avail;
672     producers = 0;
673     consumers = 0;
674     wSumAvail = 0.0;
675     lastUsage = currentTime();
676     refused = 0;
677   }
678 /**
679  * Sets the flag passBy to a new value. PassBy is indicating whether entities can
680  * pass by other entities which are enqueued before them in the queue.
681  * @param newPassBy boolean : The new value of passBy. Set it to <code>true</code>
682  * if you want entities to pass by other entities which are enqueued before them 
683  * in the queue. Set it to <code>false</code> if you don't want entities to
684  * overtake other entities in the queue.
685  */
686 public void setPassBy(boolean newPassBy) 
687 {
688   this.passBy = newPassBy;    // that's all!
689 }
690 /**
691  * Method for producers to put a number of n new products in the Bin.
692  * When producers <code>store()</code> new products n is positive. 
693  * Producers can always store products into the Bin and will never be inserted 
694  * in a queue and blocked, because the Bin has no capacity limit..
695  * @param n long : The number of products put into the Bin. 
696  */
697   public void store (long n)  
698   {    
699     where = "void store (long n)";
700     
701     SimProcess currentProcess = currentSimProcess();
702     
703     if ( !checkProcess(currentProcess, where) )  // if the current process 
704     {      return;      }                    // is not valid: just return
705     
706     if ( n <= 0)  // trying to store nothing or less, don't fool me!
707     {
708       sendWarning ( "Attempt to store nothing or a negative number of units"+
709         " in a Bin. The attempted action is ignored!" ,
710         "Bin: " + getName() + " Method: void store (long n)",
711         "It does not make sense to put nothing or less into a Bin. " +
712         "The statistic will be corrupted with negative numbers!",
713         "Make sure to store at least one unit in the Bin." );
714       return;                    // ignore it and just return
715     }
716     
717     if ( traceIsOn() )
718     {
719       sendTraceNote ( "stores " + n + " to ' " + getName() + " '" );
720     }            // tell in the trace what the process is giving into the Bin
721     
722     updateStatistics ( n );
723     
724     // see if someone is in the queue waiting for products  
725     activateFirst();            
726   }
727 /**
728  * Updates the statistics for producers and consumers.
729  * @param n long : Is positive when producers <code>store()</code> new 
730  * products in the bin and negative when the Bin <code>deliver()</code>'s
731  * products to the consumer process. 
732  */
733   protected void updateStatistics ( long n)  
734   {
735     SimTime now = currentTime();
736     wSumAvail = wSumAvail + 
737       ((double)avail * (now.getTimeValue() - lastUsage.getTimeValue()));
738     lastUsage = now;
739     avail += n;              // n can be positive or negative
740     
741     if (n > 0)                  // it is a real producer
742     {
743       producers++;
744       if (avail > maximum)
745       { maximum = avail; }
746     }
747     else                        // it is a consumer
748       { consumers++; }
749   }
750 }