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.