Implements Forks.
Internally, it represents a fork as a lock from the core library.
(Note that the Lock from the core library is not a primitive itself,
but is implemented using other primitives. Racing plays a key role
in that implementation.)
Interface to a fork. The fork itself may be shared among multiple philosophers,
in which case multiple SharedFork interfaces are created for one "physical" fork.
These SharedForks then have to coordinate when accessing the underlying "physical" fork.
Once SharedFork is successfully picked up from the table (see tryPickUp), the holder
of the resulting HeldFork can use it to eat.
Interface to a fork. The fork itself may be shared among multiple philosophers,
in which case multiple SharedFork interfaces are created for one "physical" fork.
These SharedForks then have to coordinate when accessing the underlying "physical" fork.
Once SharedFork is successfully picked up from the table (see tryPickUp), the holder
of the resulting HeldFork can use it to eat.
Attempts to pick up a shared fork. If successful, outputs HeldFork on the left.
Does not wait for the shared fork to become available. If it is unavailable,
outputs SharedFork on the right.
Attempts to pick up a shared fork. If successful, outputs HeldFork on the left.
Does not wait for the shared fork to become available. If it is unavailable,
outputs SharedFork on the right.