, the data part is almost nonexistent. The philosophers and the forks are defined as active object, for they are imbedded in the functional model. The dynamic models are implemented as finite state machines located in the bodies of the active objects. It is a very simple way for controlling the order in which the operations can happen (called or accepted) within the philosophers (lines 102 - 110 below) and within the forks (lines 206 - 209 below). The resulting program can be compiled and executed (the initialization of available is not shown).
100 active class Philosopher {
101 int i ; // philosopher’s number
102 @Philosopher () { // body
103 for (;;) {
104 think: waituntil (now ()+random ());
105 forks[i].get();
106 forks[(i+1)%5].get();
107 eat: waituntil(now()+random());
108 forks[i].put();
109 forks[(i+1)%5].put();
110 }
111 }
112 };
113 Philosopher phil[5];
201 active class Fork {
202 int available;
203 public:
204 void get() {available = 0;}
205 void put() {available = 1;}
206 @Fork () { // body
207 for (;;) {
208 accept get;
209 accept put;
210 }
211 }
212 };
213 Fork forks[5] ;
We can look at the bodies of the forks under two angles. We can consider that the operations are the important thing and that the bodies just enable the operations when they are ready. We can also consider that the forks are made of automatons (the bodies) that are synchronized with the philosophers bodies, and that the methods get and put just describe the details of the transitions. The view to be considered depends on the characteristics the programmer is developing or checking. In applications where data are important, the methods must be developed first. In reactive systems (protocols...), the automaton aspects are more important.
The functional model, which includes the shape of the network of active objects, is implemented both explicitly with the instantiations (lines 113 and 212 above) and implicitly with the passing of the number attributed to each philosopher through its constructor (not shown here).
Behavior analysis
The graph shown on Figure 4 corresponds exactly to CCS processes [2]. The functional diagram of Figure 5 corresponds to a CCS combination of two philosophers and two forks. The potential deadlock can thus be found by just applying this theory (Fig. 6), or the tool that go with it (CWB: concurrency workbench).
Fig: Composition of one philosopher and one fork
A solution without deadlock is straightforward. It does not even need any semaphore nor any other special real time feature. It simply relies on two methods (please and thankYou) by which the philosophers politely borrow the forks from their neighbors, respectively return the forks to them.
Conclusion
A lot of work has still to be done along this way, but our goal was to show that it is possible to have a global approach, accessible to the average programmer, which offers an access to the libraries of the operating system, a support for the OOP approach, modeling as well as validation. This allows the merging of several domains that are essential to a professional development of reactive applications, but were until now very far apart.
As we have seen, the dynamic model describes the behavior of the objects. The functional model describes the synchronization’s or data flows (further studies should clarify the exact difference). Once the objects are placed in their proper environment (functional model), the real time kernel can automatically find the intersection of the behaviors of the active objects, as indicated in the automatons (dynamic model) The synchronization’s are fired according to the semantic of CCS, and the analysis realized on the mod
Answered by
Sharad Singh
, an ibibo Master,
at
7:56 PM on September 01, 2008