PtGate
, PosixMonitor
and CriticalSection
provide a mutual exclusion mechanism. The classes PtCondition
and PosixCondition
provide a synchronization mechanism. The class PNGeodesic
uses these classes to implement a communication channel that enforces the blocking read operations of Kahn process networks and the blocking write operations required for bounded scheduling.
The abstract base class
PtGate
defines the interface for mutual exclusion objects in Ptolemy. The class PosixMonitor
provides an implementation of PtGate
based on the POSIX thread standard. Other implementations are possible. The class PNMonitor
is a typedef
that determines which implementation is used in the PN domain. Changing the underlying implementation simply requires changing this typedef
.PtCondition
defines the interface for condition variables in Ptolemy. The class PosixCondition
provides an implementation based on the POSIX thread standard. Other implementations are possible. The class PNCondition
is a typedef
that determines which implementation is used in the PN domain. Changing the underlying implementation simply requires changing this typedef
.CriticalSection
provides a convenient method for manipulating PtGate
objects, preventing some common programming errors. The class PNGeodesic
uses all of these classes to implement a communication channel.10.3.1 PtGate
A PtGate
can be locked and unlocked, but only one thread can hold the lock. Thus if a thread attempts to lock a PtGate
that is already locked by another thread, it is suspended until the lock is released.
virtual void lock() = 0;
This protected method locks the PtGate
object for exclusive use by one thread.
virtual void unlock() = 0;
This protected method releases the lock on the PtGate
object.
PosixMonitor
provides an implementation for the interface defined by PtGate
. It has a single protected data member.
pthread_mutex_t thread;
A handle for the POSIX monitor associated with the PosixMonitor
object.
lock
and unlock
methods are shown below.
CriticalSection
provides a convenient mechanism for locking and unlocking PtGate
objects. Its constructor, shown below, locks the gate. Its destructor, also shown below, unlocks the gate. To protect a section of code, simply create a new scope and declare an instance of CriticalSection
. The PtGate
is locked as soon as the CriticalSection
is constructed. When execution of the code exits scope, the CriticalSection
destructor is automatically invoked, unlocking the PtGate
and preventing errors caused by forgetting to unlock it. Examples of this usage are shown in Section
10.3.6. Because only one thread can hold the lock on a PtGate
, only one section of code guarded in this way can be active at a given time.
CriticalSection(PtGate* g) : mutex(g)
{
if (mutex) mutex->lock();
}
~CriticalSection()
{
if (mutex) mutex->unlock();
}10.3.4 PtCondition
The class PtCondition
defines the interface for condition variables in Ptolemy. A PtCondition
provides synchronization through the wait
and notify
methods. A condition variable can be used only when executing code within a critical section (i.e., when a PtGate
is locked).
PtGate& mon;
This data member refers to the gate associated with the PtCondition
object.
virtual void wait() = 0;
This method suspends execution of the current thread until notification is received. The associated gate is unlocked before execution is suspended. Once notification is received, the lock on the gate is automatically reacquired before execution resumes.
virtual void notify() = 0;
This method sends notification to one waiting thread. If multiple threads are waiting for notification, only one is activated.
virtual void notifyAll() = 0;
This method sends notification to all waiting threads. If multiple threads are waiting for notification, all of them are activated. Once activated, all of the threads attempt to reacquire the lock on the gate, but only one of them succeeds. The others are suspended again until they can acquire the lock on the gate.
PosixCondition
provides an implementation for the interface defined by PtCondition
. The implementations of the wait
, notify
and notifyAll
methods are shown below.
PNGeodesic
, which is derived from the class Geodesic
defined in the Ptolemy kernel, implements the communication channels for the PN domain. In conjunction with the PtGate
member provided in the base class Geodesic
, two condition variables provide the necessary synchronization for blocking read and blocking write operations.
PtCondition* notEmpty;
This data member points to a condition variable used for blocking read operations when the channel is empty.
PtCondition* notFull;
This data member points to a condition variable used for blocking write operations when the channel is full.
int cap;
This data member represents the capacity of the communication channel and determines when it is full.
static int numFull;
This static data member records the number of full geodesics in the system.
slowGet
method, shown in below, implements the get operation for communication channels. The entire method executes within a critical section to ensure consistency of the object's data members. If the buffer is empty, then the thread that invoked slowGet
is suspended until notification is received on notEmpty
. Data is retrieved from the buffer, and if it is not full notification is sent on notFull
to any other thread that may have been waiting.
slowPut
method, shown below, implements the put operation for communication channels. The entire method executes within a critical section to ensure consistency of the object's data members. If the buffer is full, then the thread that invoked slowPut
is suspended until notification is received on notFull
. Data is placed in the buffer, and notification is sent on notEmpty
to any other thread that may have been waiting.
setCapacity
method, shown below, is used to adjust the capacity limit of communication channels. If the capacity is increased so that a channel is no longer full, notification is sent on notFull
to any thread that may have been waiting.