Thank you, Stephan, for your feedback.
Below are my comments in bold based on my understanding (and please, do not hesitate to correct me if I'm mistaken).
S> \* assume that for every actor, if some action is forever enabled, it must eventually be taken
FairRead == \A a \in Readers : WF_vars(Reading(a))
FairWrite == \A a \in Writers : WF_vars(Writing(a))
FairStop == \A a \in Actors : WF_vars(StopActivity(a))
Fairness == FairRead /\ FairWrite /\ FairStop
and add Fairness to your Spec, instead of Liveness. When you now attempt to verify the liveness property for readers (formula ReaderShouldBeReading), TLC will produce a counter-example where some writer repeatedly accesses the resource but no reader ever reads.
Take the time that is needed to understand why this execution satisfies the above fairness conditions.
Y> TLC is checking the liveness property ReaderShouldBeReading and the Reading(actor) action has a weak fairness; which means that if the action Reading(actor) is enabled continuously it will eventually occur. TLC finds a path where:
* the action Writing(actor) is enabled and executed forever : this doesn't enable the action Reading(actor),
* the action Reading(actor) is enabled, but disabled again : so it’s not enabled continuously
==> Therefore, the property ReaderShouldBeReading doesn’t hold.
S> We can ensure the liveness condition for readers by changing WF to SF in the definition of FairRead, and TLC will confirm this. Again make sure you understand why this is the case.
Y> When we change the fairness condition for Reading(Actor) from WF to SF, we tell TLC that if the action Reading(actor) is enabled repeatedly, it should eventually occur, and that’s why the property ReaderShouldBeReading holds after we do this change.
S> Turning to checking liveness for writers (formula WriterShouldBeWriting), TLC will produce a more elaborate counter-example that shows you why this property does not hold, even if you replace WF by SF in the definition of FairWrite.
Y> Checking the property WriterShouldBeWriting :
- WF_vars(Writing(writer)) => We tell TLC that if the action Writing is enabled continuously, it should eventually occur.
TLC's counter-example : Readers are reading repeatedly => enabling condition of the Writing action may be true (when all readers stop reading), but not continuously, so the Action Writing never occurs! - SF_vars(Writing(writer)) => We tell TLC that if the action Writing is enabled repeatedly, it should eventually occur.
TLC's counter-example : Readers are reading and only some of them stop, so the enabling condition of the Writing action (BusyActors = {}) is never true => the property WriterShouldBeWriting never holds.
S> Take the time necessary to understand why this counter-example is fair. Now you'll have to come up with a mechanism that ensures liveness for writers, and this will require more than adding fairness conditions.