name { Share }
domain { SDF }
desc { A star with a shared data structure }
hinclude { "DataStruct.h" }
private {
static SequentialList starList;
}
output {
name { howmany }
type { int }
}
code {
SequentialList SDFShare::starList;
}
begin {
starList.append(this);
}
go {
howmany%0 << starList.size();
}
wrapup {
starList.initialize();
}
}SequentialList
with name starList.
The "static
" in C++ ensures that there will be no more than one instance of the SequentialList
object. That instance will be accessible to every instance of the star, but not to any other object (because the member is private). That one instance is actually declared by the lines:
SequentialList SDFShare::starList;
}SDFShare.cc
by the preprocessor. Notice that the class name of the star is SDFShare
not just Share
. The begin
method simply adds to the sequential list a pointer to the star that invoked the begin
method (this
). Note that you should use the begin
method here rather than the setup
method because the begin
method is always invoked exactly once, while the setup
method might be invoked more than once when the simulation starts up. The go
method sends to the output (named howmany
) the size of the list. This will be equal to the number of stars of this type in the universe.wrapup
method has the only tricky part of this code. It reinitializes the SequentialList
so that subsequent runs do not just simply add to a list created by previous runs. However, note that the wrapup method will not be invoked if an error occurs during the run. Pigi
ensures correct operation nonetheless by deleting all instances of the stars and recreating them if an error occurred on the previous run. Thus, between invocations of the begin
method, either the wrapup
method or the constructor for the star (and all its members) will be invoked. The constructor for SequentialList
also initializes the list, so the list is always initialized before the first begin
method is called.HashTable
. So for example, suppose we wanted to modify the above star to create lists of stars with common values of a parameter "mySubset", and to output the number of stars in their subset. The above code becomes:
name { BetterShare }
domain { SDF }
desc { A star with a shared data structure }
hinclude { "DataStruct.h" }
hinclude { "HashTable.h" }
output {
name { howmany }
type { int }
}
state {
name { mySubset }
default { "subset A" }
type { string }
}
private {
static HashTable listOfLists;
SequentialList* myList;
}
code {
HashTable SDFBetterShare::listOfLists;
}
begin {
if (listOfLists.hasKey((char*)mySubset)) {
myList = listOfLists.lookup((char*)mySubset);
} else {
myList = new SequentialList;
listOfLists.insert((char*)mySubset,myList);
}
myList->append(this);
}
go {
howmany%0 << myList->size();
}
wrapup {
if (listOfLists.hasKey((char*)mySubset)) {
listOfLists.remove((char*)mySubset);
delete myList;
}
}
}listOfLists
, we also have a pointer myList
to a SequentialList
. The begin
method is a bit more complicated now. It first checks to see whether an entry in the hash table has already been created with a key equal to the value of the state "mySubset". If it has, then the SequentialList
pointer myList
is set equal to the value of that entry. If it has not, then a new SequentialList
is allocated and inserted into the hash table with the appropriate key. The last action is simply to insert a pointer to the star instance into myList
. go
method is similar to before. wrapup
method is slightly more complicated, because it needs to free the memory allocated when the new SequentialList
was allocated. However, it should free that memory only once, and there may be several star instances pointing to it. Thus, it first checks the hash table to see whether there exists an entry with key equal to mySubset
. If there does, then it removes that entry and deletes the SequentialList
myList
.
Copyright © 1990-1997, University of California. All rights reserved.