This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/Logtalk/examples/threads/philosophers/philosophers.lgt
pmoura e75e406f84 Logtalk 2.29.2 files.
git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1773 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
2007-01-10 12:46:10 +00:00

226 lines
4.2 KiB
Plaintext

:- category(chopstick).
:- info([
version is 1.2,
author is 'Paulo Moura',
date is 2006/12/31,
comment is 'Dining philosophers problem: chopstick representation.']).
:- public(pick_up/0).
:- mode(pick_up, zero_or_one).
:- info(pick_up/0, [
comment is 'A Philosopher picks up the chopstick.']).
:- public(put_down/0).
:- mode(put_down, zero_or_one).
:- info(put_down/0, [
comment is 'A Philosopher puts down the chopstick.']).
:- private(available/0).
:- dynamic(available/0).
:- mode(available, zero_or_one).
:- info(available/0, [
comment is 'Chopstick state (either available or in use).']).
% chopstick actions (picking up and putting down) are synchronized using the same mutext
% such that a chopstick can only be handled by a single philosopher at a time:
:- synchronized([pick_up/0, put_down/0]).
pick_up :-
::available,
::retract(available).
put_down :-
\+ ::available,
::asserta(available).
:- end_category.
:- object(cs1,
imports(chopstick)).
:- dynamic(available/0).
available.
:- end_object.
:- object(cs2,
imports(chopstick)).
:- dynamic(available/0).
available.
:- end_object.
:- object(cs3,
imports(chopstick)).
:- dynamic(available/0).
available.
:- end_object.
:- object(cs4,
imports(chopstick)).
:- dynamic(available/0).
available.
:- end_object.
:- object(cs5,
imports(chopstick)).
:- dynamic(available/0).
available.
:- end_object.
:- category(philosopher).
:- info([
version is 1.1,
author is 'Paulo Moura',
date is 2007/1/3,
comment is 'Dining philosophers problem: philosopher representation.']).
:- public(left_chopstick/1).
:- mode(left_chopstick(?object_identifier), zero_or_one).
:- info(left_chopstick/1, [
comment is 'Chopstick at the left of a philosopher.',
argnames is ['Chopstick']]).
:- public(right_chopstick/1).
:- mode(right_chopstick(?object_identifier), zero_or_one).
:- info(right_chopstick/1, [
comment is 'Chopstick at the right of a philosopher.',
argnames is ['Chopstick']]).
:- public(run/2).
:- mode(run(+integer, +integer), one).
:- info(run/2, [
comment is 'Runs Count number of thinking/eating cycles, with each activity taking MaxTime (in seconds).',
argnames is ['Count', 'MaxTime']]).
:- private(message/1).
:- synchronized(message/1).
:- mode(message(+list), one).
:- info(message/1, [
comment is 'Writes all the terms on a list as an atomic operation.',
argnames is ['Atoms']]).
:- uses(random, [random/3]).
run(0, _) :-
this(Philosopher),
message([Philosopher, ' terminated.']).
run(Count, MaxTime) :-
think(MaxTime),
( eat(MaxTime) ->
Count2 is Count - 1,
run(Count2, MaxTime)
; run(Count, MaxTime)
).
think(MaxTime):-
this(Philosopher),
random(1, MaxTime, ThinkTime),
message(['Philosopher ', Philosopher, ' thinking for ', ThinkTime, ' seconds.']),
thread_sleep(ThinkTime).
% deadlock while a philosopher is trying to eat is prevented by putting
% down the first chopstick when picking up the second one fails:
eat(MaxTime):-
this(Philosopher),
random(1, MaxTime, EatTime),
::left_chopstick(LeftStick),
::right_chopstick(RightStick),
LeftStick::pick_up,
( RightStick::pick_up ->
message(['Philosopher ', Philosopher, ' eating for ', EatTime, ' seconds with chopsticks ', LeftStick, ' and ', RightStick, '.']),
thread_sleep(EatTime),
::LeftStick::put_down,
::RightStick::put_down
; ::LeftStick::put_down,
fail
).
% writing a message needs to be synchronized as it's accomplished
% using a combination of individual write/1 (and nl/0) calls:
message([]) :-
nl,
flush_output.
message([Atom| Atoms]) :-
write(Atom),
message(Atoms).
:- end_category.
:- object(p1,
imports(philosopher)).
:- threaded.
left_chopstick(cs5).
right_chopstick(cs1).
:- end_object.
:- object(p2,
imports(philosopher)).
:- threaded.
left_chopstick(cs1).
right_chopstick(cs2).
:- end_object.
:- object(p3,
imports(philosopher)).
:- threaded.
left_chopstick(cs3).
right_chopstick(cs2).
:- end_object.
:- object(p4,
imports(philosopher)).
:- threaded.
left_chopstick(cs4).
right_chopstick(cs3).
:- end_object.
:- object(p5,
imports(philosopher)).
:- threaded.
left_chopstick(cs5).
right_chopstick(cs4).
:- end_object.