KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > DiningPhilosophers > monolithic > 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.monolithic;
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 org.omg.CORBA.LocalObject JavaDoc
51   implements CCM_Philosopher,
52              java.lang.Runnable JavaDoc,
53              org.omg.Components.SessionComponent
54 {
55     // ==================================================================
56
//
57
// Internal state.
58
//
59
// ==================================================================
60

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

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

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

104     private int[] stateDuration = {-1, 3, 10, 40, -1};
105
106     /** Icons used to represent the philosopher state. */
107     private java.awt.Image JavaDoc[] stateAsIcon;
108
109     // ==================================================================
110
//
111
// Constructor.
112
//
113
// ==================================================================
114

115     /**
116      * The default constructor.
117      *
118      * Init a philosopher with an empty name.
119      */

120     public
121     PhilosopherPdaImpl()
122     {
123         this(null);
124     }
125
126     /**
127      * The constructor.
128      *
129      * @param name The philosopher name.
130      */

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

166     /**
167      * The philosopher enter in thinking state.
168      * This represents actions to do during one tick.
169      *
170      * During this state, the philosopher think. When the hungryness
171      * becomes three, the philosopher goes to the hungry state.
172      */

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

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

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

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

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

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

442     protected void
443     setStatus(PhilosopherState state)
444     {
445         state_ = state;
446
447         button_.setIcon(stateAsIcon[state_.value()]);
448         // frame_.pack();
449
// frame_.show();
450

451         // Pushes an event to the connected observer.
452
the_context_.push_info(new StatusInfoImpl(state_, name_,
453                                                    hungryness_, left_fork_,
454                                                    right_fork_));
455     }
456
457     // ==================================================================
458
//
459
// Public methods.
460
//
461
// ==================================================================
462

463     // ==================================================================
464
//
465
// Methods for OMG IDL Components::EnterpriseComponent
466
//
467
// ==================================================================
468

469     /**
470      * Complete the component configuration.
471      *
472      * <p>
473      * Checks philosopher name, ticks duration, forks connections
474      * and starts the philosopher behaviour.
475      * </p>
476      *
477      * @exception org.omg.Components.InvalidConfiguration
478      * Thrown if the configuration is invalid.
479      */

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

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

532     /**
533      * Setting the session component context.
534      *
535      * @param context The session component context.
536      */

537     public void
538     set_session_context(org.omg.Components.SessionContext context)
539     throws org.omg.Components.CCMException
540     {
541         the_context_ = (CCM_Philosopher_Context)context;
542     }
543
544     /**
545      * Container callback to signal that the component is activated.
546      *
547      * @throw org.omg.Components.CCMException For any problems.
548      */

549     public void
550     ccm_activate()
551     throws org.omg.Components.CCMException
552     {
553         // Nothing to do currently.
554
}
555
556     /**
557      * Container callback to signal that the component is activated.
558      *
559      * @throw org.omg.Components.CCMException For any problems.
560      */

561     public void
562     ccm_passivate()
563     throws org.omg.Components.CCMException
564     {
565         // Nothing to do currently.
566
}
567
568     /**
569      * Container callback to signal that the component is removed.
570      *
571      * @throw org.omg.Components.CCMException For any problems.
572      */

573     public void
574     ccm_remove()
575     throws org.omg.Components.CCMException
576     {
577         // Release the associated frame.
578
frame_.dispose();
579         frame_ = null;
580
581         // Stop the philosopher behaviour.
582
behaviour_.stop();
583         behaviour_ = null;
584     }
585
586     // ==================================================================
587
//
588
// Methods for OMG IDL DiningPhilosophers::Philosopher
589
//
590
// ==================================================================
591

592     /**
593      * The mutator method for the attribute name.
594      *
595      * @param n The name.
596      */

597     public void
598     name(String JavaDoc n)
599     {
600         name_ = n;
601     }
602
603     /**
604      * The accessor method for the attribute name.
605      *
606      * @return The name.
607      */

608     public String JavaDoc
609     name()
610     {
611         return name_;
612     }
613
614     // ==================================================================
615
//
616
// Methods for interface java.lang.Runnable
617
//
618
// ==================================================================
619

620     /**
621      * The philosopher behaviour.
622      */

623     public void
624     run()
625     {
626         // The philosopher starts thinking.
627
setStatus(PhilosopherState.THINKING);
628         nextTick();
629     }
630 }
631
632 /**
633  * An internal button GUI for PDA (based on AWT).
634  */

635 class MyButton extends java.awt.Panel JavaDoc
636 {
637
638     /** used icons */
639     protected java.awt.Image JavaDoc icon_;
640
641     /**
642      * Default constructor.
643      */

644     public MyButton() {
645     };
646
647     /**
648      * Set the icon to use when check box hasn't been selected.
649      */

650     public void setIcon(java.awt.Image JavaDoc icon)
651     {
652         icon_ = icon;
653         repaint();
654     }
655
656     /**
657      * Overrides java.awt.Component.getPreferredSize
658      * in order to have a nice display of icons.
659      */

660     public java.awt.Dimension JavaDoc getPreferredSize()
661     {
662         return new java.awt.Dimension JavaDoc(100, 100);
663     }
664
665     /**
666      * Overrides the component paint method to draw
667      * icon.
668      */

669      public void paint(java.awt.Graphics JavaDoc g)
670      {
671          g.drawImage(icon_, 0, 0, this);
672      }
673 }
674
Popular Tags