KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > DiningPhilosophers > cif > PhilosopherPdaImpl


1 /*====================================================================
2
3 OpenCCM: The Open CORBA Component Model Platform
4 Copyright (C) 2000-2002 USTL - LIFL - GOAL
5 Contact: openccm-team@objectweb.org
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA
21
22 Initial developer(s): Philippe Merle, Sylvain Leblanc.
23 Contributor(s): Christophe Demarey.
24
25 ====================================================================*/

26
27 package DiningPhilosophers.cif;
28
29 import DiningPhilosophers.*;
30
31 /**
32  * This is the implementation of the OMG IDL3
33  * DiningPhilosophers::Philosopher component type.
34  *
35  * This class inherits from the local CCM_Philosopher interface
36  * generated by the OpenCCM's IDL3 to IDL2 mapping generator.
37  *
38  * This class also implements the Runnable interface to execute
39  * the philosopher behavior into a thread.
40  *
41  * @author <a HREF="mailto:Philippe.Merle@lifl.fr">Philippe Merle</a>
42  * @author <a HREF="mailto:Sylvain.Leblanc@lifl.fr">Sylvain Leblanc</a>
43  * @author <a HREF="mailto:Christophe.Demarey@lifl.fr">Christophe Demarey</a>
44  *
45  * @version 2.0
46  *
47  */

48
49 public class PhilosopherPdaImpl
50      extends DiningPhilosophers.PhilosopherSessionComposition.PhilosopherSession_impl
51   implements java.lang.Runnable JavaDoc
52 {
53     // ==================================================================
54
//
55
// Internal state.
56
//
57
// ==================================================================
58

59     /** The philosopher name. */
60     private String JavaDoc name_;
61
62     /**
63      * The philosopher ticks duration.
64      * This value is computed during initialization.
65      */

66     private int ticks_duration_ = 0;
67
68     /** The philosopher hungryness counter. */
69     private int hungryness_;
70
71     /**
72      * The counter for hold since how many ticks
73      * the philosopher hold a fork when in hungry state.
74      */

75     private int hungry_counter_;
76
77     /** Tells if the philosopher have got his left fork. */
78     private boolean left_fork_;
79
80     /** Tells if the philosopher have got his right fork. */
81     private boolean right_fork_;
82
83     /** Contains the philosopher behaviour as a state machine. */
84     private java.lang.Thread JavaDoc behaviour_;
85
86     /** The philosopher current status. */
87     private PhilosopherState state_;
88
89     /** The philosopher frame */
90     private java.awt.Frame JavaDoc frame_;
91
92     /** The philosopher icon button */
93     private MyButton button_;
94
95     /**
96      * Represents duration for EATING, THINKING, HUNGRY,
97      * STARVING and DEAD states.
98      */

99     private int[] stateDuration = {-1, 3, 10, 40, -1};
100
101     /** Icons used to represent the philosopher state. */
102     private java.awt.Image JavaDoc[] stateAsIcon;
103
104     // ==================================================================
105
//
106
// Constructor.
107
//
108
// ==================================================================
109

110     /**
111      * The default constructor.
112      *
113      * Init a philosopher with an empty name.
114      */

115     public
116     PhilosopherPdaImpl()
117     {
118         this(null);
119     }
120
121     /**
122      * The constructor.
123      *
124      * @param name The philosopher name.
125      */

126     public
127     PhilosopherPdaImpl(String JavaDoc name)
128     {
129         name_ = name;
130         java.util.Random JavaDoc rand =
131             new java.util.Random JavaDoc(System.currentTimeMillis());
132         ticks_duration_ = 1000 + rand.nextInt(2001);
133         left_fork_ = false;
134         right_fork_ = false;
135         state_ = null;
136         behaviour_ = null;
137         hungry_counter_=0;
138         hungryness_=0;
139
140         // Creates the icon tab. Each icon must be in the jar archive.
141
stateAsIcon = new java.awt.Image JavaDoc[5];
142         java.net.URL JavaDoc url = PhilosopherPdaImpl.class.getResource("/images/eat.gif");
143         stateAsIcon[0] = java.awt.Toolkit.getDefaultToolkit().getImage(url);
144         url = PhilosopherPdaImpl.class.getResource("/images/think.gif");
145         stateAsIcon[1] = java.awt.Toolkit.getDefaultToolkit().getImage(url);
146         url = PhilosopherPdaImpl.class.getResource("/images/hun.gif");
147         stateAsIcon[2] = java.awt.Toolkit.getDefaultToolkit().getImage(url);
148         url = PhilosopherPdaImpl.class.getResource("/images/hun_right.gif");
149         stateAsIcon[3] = java.awt.Toolkit.getDefaultToolkit().getImage(url);
150         url = PhilosopherPdaImpl.class.getResource("/images/rip.jpg");
151         stateAsIcon[4] = java.awt.Toolkit.getDefaultToolkit().getImage(url);
152
153     }
154
155     // ==================================================================
156
//
157
// Internal methods.
158
//
159
// ==================================================================
160

161     /**
162      * The philosopher enter in thinking state.
163      * This represents actions to do during one tick.
164      *
165      * During this state, the philosopher think. When the hungryness
166      * becomes three, the philosopher goes to the hungry state.
167      */

168     protected void
169     inThinkingState()
170     {
171         if (hungryness_ < stateDuration[PhilosopherState._THINKING])
172         {
173             setStatus(PhilosopherState.THINKING);
174         } else {
175             setStatus(PhilosopherState.HUNGRY);
176         }
177     }
178
179     /**
180      * The philosopher enter in hungry state.
181      * This represents actions to do during one tick.
182      *
183      * <p>
184      * During this state, the philosopher would like to eat,
185      * so the philosopher attempts to acquire both forks.
186      * If the philosopher succeeds getting both forks, the
187      * philosopher enters the eating state. If the philosopher
188      * does not succeed getting both forks since hungryness is
189      * ten, the philosopher enter the starving state.
190      * </p>
191      *
192      * <p>
193      * The philosopher is not allowed to hold a single fork
194      * for an extended amount of time. If the philosopher hold a
195      * fork while waiting for the other one, the fork held by the
196      * philosopher must be released after five ticks.
197      * </p>
198      */

199     protected void
200     inHungryState()
201     {
202         // trying to get the left fork
203
if (! left_fork_)
204         {
205             try {
206                 get_context().get_connection_left().get();
207                 left_fork_ = true;
208                 hungry_counter_=0;
209             } catch(InUse exc) {
210                 if (right_fork_ && hungry_counter_ >= 5) {
211                     // release the right fork.
212
get_context().get_connection_right().release();
213                     right_fork_=false;
214                     hungry_counter_=0;
215                 }
216             }
217         }
218
219         // trying to get the right fork
220
if (! right_fork_)
221         {
222             try {
223                 get_context().get_connection_right().get();
224                 right_fork_ = true;
225                 hungry_counter_=0;
226             } catch(InUse exc) {
227                 if (left_fork_ && hungry_counter_ >= 5) {
228                     // release the left fork.
229
get_context().get_connection_left().release();
230                     left_fork_=false;
231                     hungry_counter_=0;
232                 }
233             }
234         }
235
236         if (left_fork_ && right_fork_) {
237             hungry_counter_=0;
238             // enter eating state.
239
setStatus(PhilosopherState.EATING);
240         } else if (hungryness_ >= stateDuration[PhilosopherState._HUNGRY]) {
241             hungry_counter_=0;
242             // enter startving state.
243
setStatus(PhilosopherState.STARVING);
244         } else {
245             hungry_counter_++;
246             // enter hungry state.
247
setStatus(PhilosopherState.HUNGRY);
248         }
249     }
250
251     /**
252      * The philosopher enter in starving state.
253      * This represents actions to do during one tick.
254      *
255      * <p>
256      * During this state, the philosopher acts as in the previous
257      * state but can hold a fork for an extended amount of time
258      * while waiting for the other one.
259      * If the philosopher succeeds getting both forks, the
260      * philosopher enters the eating state. If the philosopher
261      * does not succeed getting both forks since hungryness is
262      * forty, the philosopher enter the dead state.
263      * </p>
264      */

265     protected void
266     inStarvingState()
267     {
268         // trying to get the left fork
269
if (! left_fork_)
270         {
271             try {
272                 get_context().get_connection_left().get();
273                 left_fork_ = true;
274             } catch(InUse exc) {
275             }
276         }
277
278         // trying to get the right fork
279
if (! right_fork_)
280         {
281             try {
282                 get_context().get_connection_right().get();
283                 right_fork_ = true;
284             } catch(InUse exc) {
285             }
286         }
287
288         if (left_fork_ && right_fork_) {
289             // enter eating state.
290
setStatus(PhilosopherState.EATING);
291         } else if (hungryness_ < stateDuration[PhilosopherState._STARVING]) {
292             // enter starving state.
293
setStatus(PhilosopherState.STARVING);
294         } else {
295             // enter dead state.
296
setStatus(PhilosopherState.DEAD);
297         }
298     }
299
300     /**
301      * The philosopher enter in eating state.
302      * This represents actions to do during one tick.
303      *
304      * <p>
305      * During this state, the philosopher holds on to both forks
306      * and spend one-third of the time eating thaht the philosopher
307      * was thinking, hungry or starving. When the philosopher stop
308      * to eat, he drops both forks and enters in thinking state.
309      * </p>
310      */

311     protected void
312     inEatingState()
313     {
314         if (hungryness_ > 0)
315         {
316             // enter eating state.
317
setStatus(PhilosopherState.EATING);
318             // eating...
319
hungryness_-=3;
320         } else {
321             hungryness_ = 0;
322             // release the left fork.
323
if (left_fork_)
324                 {
325                     get_context().get_connection_left().release();
326                     left_fork_ = false;
327                 }
328             // release the right fork.
329
if (right_fork_)
330                 {
331                     get_context().get_connection_right().release();
332                     right_fork_ = false;
333                 }
334             // enter thinking state.
335
setStatus(PhilosopherState.THINKING);
336         }
337     }
338
339     /**
340      * The philosopher enter in dead state.
341      * This represents actions to do during one tick.
342      *
343      * <p>
344      * During this state the philosopher releases both forks and
345      * do nothing else. This is no way out of the dead state.
346      * </p>
347      */

348     protected void
349     inDeadState()
350     {
351         // release the left fork.
352
if (left_fork_)
353         {
354             get_context().get_connection_left().release();
355             left_fork_ = false;
356         }
357         // release the right fork.
358
if (right_fork_)
359         {
360             get_context().get_connection_right().release();
361             right_fork_ = false;
362         }
363         // enter dead state.
364
setStatus(PhilosopherState.DEAD);
365     }
366
367     /**
368      * Process state value and waiting next tick.
369      * Resolving the state machine transitions.
370      *
371      * <p>
372      * When calling <code>nextTick</code>, the
373      * philosopher status is processed to enter
374      * in the appropriate state. Then, waiting for
375      * the next tick and callback itself.
376      * </p>
377      */

378     protected void
379     nextTick()
380     {
381         // choose state to go
382
switch(state_.value())
383         {
384         case PhilosopherState._EATING :
385             {
386                 inEatingState();
387                 break;
388             }
389         case PhilosopherState._THINKING :
390             {
391                 inThinkingState();
392                 break;
393             }
394         case PhilosopherState._HUNGRY :
395             {
396                 inHungryState();
397                 break;
398             }
399         case PhilosopherState._STARVING :
400             {
401                 inStarvingState();
402                 break;
403             }
404         case PhilosopherState._DEAD :
405             {
406                 inDeadState();
407                 break;
408             }
409         }
410
411         // waiting next tick.
412
try {
413             behaviour_.sleep(ticks_duration_);
414         } catch(java.lang.InterruptedException JavaDoc exc) {
415             exc.printStackTrace();
416         }
417
418         // Test if hungryness counter must be incremented.
419
switch (state_.value())
420         {
421         case PhilosopherState._THINKING :
422         case PhilosopherState._HUNGRY :
423         case PhilosopherState._STARVING :
424             {
425                 hungryness_++;
426                 break;
427             }
428         }
429
430         // call the next trick
431
nextTick();
432     }
433
434     /**
435      * Change the status and send an event by the info source.
436      */

437     protected void
438     setStatus(PhilosopherState state)
439     {
440         state_ = state;
441
442         button_.setIcon(stateAsIcon[state_.value()]);
443         // frame_.pack();
444
// frame_.show();
445

446         // Pushes an event to the connected observer.
447
get_context().push_info(new StatusInfoImpl(state_, name_,
448                                                    hungryness_, left_fork_,
449                                                    right_fork_));
450     }
451
452     // ==================================================================
453
//
454
// Public methods.
455
//
456
// ==================================================================
457

458     // ==================================================================
459
//
460
// Methods for OMG IDL Components::EnterpriseComponent
461
//
462
// ==================================================================
463

464     /**
465      * Complete the component configuration.
466      *
467      * <p>
468      * Checks philosopher name, ticks duration, forks connections
469      * and starts the philosopher behaviour.
470      * </p>
471      *
472      * @exception org.omg.Components.InvalidConfiguration
473      * Thrown if the configuration is invalid.
474      */

475     public void
476     configuration_complete()
477     throws org.omg.Components.InvalidConfiguration
478     {
479         // Checks if the configuration is completed.
480
if(name_ == null)
481             throw new org.omg.Components.InvalidConfiguration();
482
483         // Checks if the configuration is completed.
484
if(ticks_duration_ == 0)
485             throw new org.omg.Components.InvalidConfiguration();
486
487         // Check if the connection to the left fork is set.
488
if(get_context().get_connection_left() == null)
489             throw new org.omg.Components.InvalidConfiguration();
490
491         // Check if the connection to the right fork is set.
492
if(get_context().get_connection_right() == null)
493             throw new org.omg.Components.InvalidConfiguration();
494
495         // Creates the Philosopher GUI
496
frame_ = new java.awt.Frame JavaDoc(name_ + " GUI");
497         java.awt.Panel JavaDoc border = new java.awt.Panel JavaDoc(new java.awt.BorderLayout JavaDoc());
498
499         // Creates the icon button
500
button_ = new MyButton();
501         button_.setIcon(stateAsIcon[PhilosopherState._THINKING]);
502
503         // Setting up a label
504
java.awt.Label JavaDoc label = new java.awt.Label JavaDoc("Hi ! I'm " + name_ + " !!");
505         // label.setFont(label.getFont().deriveFont((float)16.0));
506

507         // Packing the GUI
508
border.add(button_, java.awt.BorderLayout.CENTER);
509         border.add(label, java.awt.BorderLayout.SOUTH);
510         frame_.add(border);
511
512         // Display the GUI
513
frame_.pack();
514         frame_.show();
515
516         // Start the behaviour.
517
behaviour_ = new java.lang.Thread JavaDoc(this);
518         behaviour_.start();
519     }
520
521     // ==================================================================
522
//
523
// Methods for the OMG IDL org.omg.Components.SessionComponent
524
//
525
// ==================================================================
526

527     /**
528      * Container callback to signal that the component is removed.
529      *
530      * @throw org.omg.Components.CCMException For any problems.
531      */

532     public void
533     ccm_remove()
534     throws org.omg.Components.CCMException
535     {
536         // Release the associated frame.
537
frame_.dispose();
538         frame_ = null;
539
540         // Stop the philosopher behaviour.
541
behaviour_.stop();
542         behaviour_ = null;
543     }
544
545     // ==================================================================
546
//
547
// Methods for OMG IDL DiningPhilosophers::Philosopher
548
//
549
// ==================================================================
550

551     /**
552      * The mutator method for the attribute name.
553      *
554      * @param n The name.
555      */

556     public void
557     name(String JavaDoc n)
558     {
559         name_ = n;
560     }
561
562     /**
563      * The accessor method for the attribute name.
564      *
565      * @return The name.
566      */

567     public String JavaDoc
568     name()
569     {
570         return name_;
571     }
572
573     // ==================================================================
574
//
575
// Methods for interface java.lang.Runnable
576
//
577
// ==================================================================
578

579     /**
580      * The philosopher behaviour.
581      */

582     public void
583     run()
584     {
585         // The philosopher starts thinking.
586
setStatus(PhilosopherState.THINKING);
587         nextTick();
588     }
589 }
590
591 /**
592  * An internal button GUI for PDA (based on AWT).
593  */

594 class MyButton extends java.awt.Panel JavaDoc
595 {
596
597     /** used icons */
598     protected java.awt.Image JavaDoc icon_;
599
600     /**
601      * Default constructor.
602      */

603     public MyButton() {
604     };
605
606     /**
607      * Set the icon to use when check box hasn't been selected.
608      */

609     public void setIcon(java.awt.Image JavaDoc icon)
610     {
611         icon_ = icon;
612         repaint();
613     }
614
615     /**
616      * Overrides java.awt.Component.getPreferredSize
617      * in order to have a nice display of icons.
618      */

619     public java.awt.Dimension JavaDoc getPreferredSize()
620     {
621         return new java.awt.Dimension JavaDoc(100, 100);
622     }
623
624     /**
625      * Overrides the component paint method to draw
626      * icon.
627      */

628      public void paint(java.awt.Graphics JavaDoc g)
629      {
630          g.drawImage(icon_, 0, 0, this);
631      }
632 }
633
Popular Tags