
:- ensure_loaded(lockrw).

go :-
	thread_create(t, _, [alias(bart)]),
	thread_create(t, _, [alias(lisa)]),
	thread_create(t, _, [alias(homer)]),
	thread_create(t, _, [alias(marge)]),
	thread_report(bart),
	thread_report(lisa),
	thread_report(homer),
	thread_report(marge),
	check.

check :-
	findall(X, step(X), Steps),
	findall(X, expected_step(X), ExpectedSteps),
	Steps = ExpectedSteps.

thread_report(Id) :-
	thread_join(Id, Status),
	assertz(step(ended(Id, Status))).
	% format(' ~a ended (~p)~n', [Id, Status]).

t :-
	with_read_lock(phone, (log(read), sleep(0.03), log(un_read))),
	with_write_lock(phone, (log(write), sleep(0.03), log(un_write))),
	with_read_lock(phone, (log(read), sleep(0.03), log(un_read))),
	with_write_lock(phone, (log(write), sleep(0.03), log(un_write))).

log(Op) :-
	thread_self(Me),
	assertz(step(did(Op, Me))).

expected_step(did(read, bart)).
expected_step(did(read, lisa)).
expected_step(did(read, homer)).
expected_step(did(read, marge)).
expected_step(did(un_read, bart)).
expected_step(did(un_read, lisa)).
expected_step(did(un_read, homer)).
expected_step(did(un_read, marge)).
expected_step(did(write, bart)).
expected_step(did(un_write, bart)).
expected_step(did(write, lisa)).
expected_step(did(un_write, lisa)).
expected_step(did(write, homer)).
expected_step(did(un_write, homer)).
expected_step(did(write, marge)).
expected_step(did(un_write, marge)).
expected_step(did(read, marge)).
expected_step(did(read, bart)).
expected_step(did(read, lisa)).
expected_step(did(read, homer)).
expected_step(did(un_read, marge)).
expected_step(did(un_read, bart)).
expected_step(did(un_read, lisa)).
expected_step(did(un_read, homer)).
expected_step(did(write, marge)).
expected_step(did(un_write, marge)).
expected_step(did(write, bart)).
expected_step(did(un_write, bart)).
expected_step(ended(bart, true)).
expected_step(did(write, lisa)).
expected_step(did(un_write, lisa)).
expected_step(ended(lisa, true)).
expected_step(did(write, homer)).
expected_step(did(un_write, homer)).
expected_step(ended(homer, true)).
expected_step(ended(marge, true)).
