Logtalk 2.29.1 files.
git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1744 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.28.2
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
@@ -9,5 +9,5 @@ Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
This folder contains some examples of multi-threading programming.
|
||||
Multi-threading programming is only supported on some Prolog compilers.
|
||||
Currently this includes SWI-Prolog and YAP. Moreover, multi-threading
|
||||
is turned off by default. In order to run the examples, you will need
|
||||
may be turned off by default. In order to run the examples, you may need
|
||||
to first turn on multi-threading support on the Prolog config files.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.28.2
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
@@ -1,18 +1,12 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.28.2
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
||||
|
||||
% start by loading the "event_handlersp" protocol:
|
||||
|
||||
| ?- logtalk_load(library(event_handlersp)).
|
||||
...
|
||||
|
||||
|
||||
% now you are ready for loading the example:
|
||||
% load the example:
|
||||
|
||||
| ?- logtalk_load(birthdays(loader)).
|
||||
...
|
||||
|
@@ -1,11 +1,11 @@
|
||||
|
||||
:- object(agent,
|
||||
implements(event_handlersp)).
|
||||
implements(monitoring)).
|
||||
|
||||
:- info([
|
||||
version is 1.0,
|
||||
author is 'Peter Robinson and Paulo Moura',
|
||||
date is 2006/04/09,
|
||||
version is 1.2,
|
||||
author is 'Paulo Moura and Peter Robinson',
|
||||
date is 2006/12/27,
|
||||
comment is 'Simple multi-threading example with agents and their birthdays.']).
|
||||
|
||||
:- threaded.
|
||||
@@ -57,34 +57,42 @@
|
||||
comment is 'New friend, watch out for his/her birthday.',
|
||||
argnames is ['Name']]).
|
||||
|
||||
% new agents are created as threaded objects:
|
||||
new(Name, Age, Gender) :-
|
||||
this(This),
|
||||
create_object(Name, [extends(This)], [threaded], [age(Age), gender(Gender)]).
|
||||
|
||||
% ask a friend's age using an asynchronous message:
|
||||
ask_age(Friend, Age) :-
|
||||
threaded_call(Friend::age(Age)),
|
||||
threaded_exit(Friend::age(Age)).
|
||||
|
||||
% getting older:
|
||||
birthday :-
|
||||
::retract(age(Old)),
|
||||
New is Old + 1,
|
||||
::assertz(age(New)).
|
||||
|
||||
% when someone congratulate us for our birthday, acknowledge it,
|
||||
% and offer her/him a slice of the birthday cake:
|
||||
happy_birthday(From) :-
|
||||
self(Self),
|
||||
write('Happy birthday from '), write(From), write('!'), nl,
|
||||
write('Thanks! Here, have a slice of cake, '), write(From), write('.'), nl,
|
||||
threaded_call(From::cake_slice(Self), [noreply]).
|
||||
threaded_ignore(From::cake_slice(Self)).
|
||||
|
||||
% be nice, give thanks for the cake offer:
|
||||
cake_slice(From) :-
|
||||
write('Thanks for the cake '), write(From), write('!'), nl.
|
||||
|
||||
% whatch out for our new friend anniversary:
|
||||
new_friend(Friend) :-
|
||||
self(Self),
|
||||
define_events(after, Friend, birthday, _, Self).
|
||||
|
||||
% congratule a friend for his/her birthday:
|
||||
after(Friend, birthday, _) :-
|
||||
self(Self),
|
||||
threaded_call(Friend::happy_birthday(Self), [noreply]).
|
||||
threaded_ignore(Friend::happy_birthday(Self)).
|
||||
|
||||
:- end_object.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.28.2
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
@@ -1,6 +1,6 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.28.2
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
@@ -2,9 +2,9 @@
|
||||
:- protocol(find_rootp).
|
||||
|
||||
:- info([
|
||||
version is 1.0,
|
||||
date is 2006/4/21,
|
||||
author is 'Paulo Nunes',
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura and Paulo Nunes',
|
||||
date is 2006/11/26,
|
||||
comment is 'Default protocol for root find algorithms.']).
|
||||
|
||||
:- public(find_root/5).
|
||||
@@ -25,9 +25,9 @@
|
||||
:- protocol(functionp).
|
||||
|
||||
:- info([
|
||||
version is 1.0,
|
||||
date is 2006/4/21,
|
||||
author is 'Paulo Nunes',
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura and Paulo Nunes',
|
||||
date is 2006/11/26,
|
||||
comment is 'Default protocol for real functions of a single real variable.']).
|
||||
|
||||
:- public(eval/2).
|
||||
@@ -93,9 +93,9 @@
|
||||
implements(find_rootp)).
|
||||
|
||||
:- info([
|
||||
version is 1.0,
|
||||
date is 2006/4/21,
|
||||
author is 'Paulo Nunes',
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura and Paulo Nunes',
|
||||
date is 2006/11/26,
|
||||
comment is 'Multi-threading interface to root finding algorithms.']).
|
||||
|
||||
:- threaded.
|
||||
@@ -104,7 +104,7 @@
|
||||
find_root(Function, A, B, Error, Zero, _).
|
||||
|
||||
find_root(Function, A, B, Error, Zero, Algorithm) :-
|
||||
threaded_call(
|
||||
threaded_race(
|
||||
( try_method(bisection, Function, A, B, Error, Zero)
|
||||
; try_method(newton, Function, A, B, Error, Zero)
|
||||
; try_method(muller, Function, A, B, Error, Zero)
|
||||
@@ -121,9 +121,9 @@
|
||||
implements(find_rootp)).
|
||||
|
||||
:- info([
|
||||
version is 1.0,
|
||||
date is 2006/4/21,
|
||||
author is 'Paulo Nunes',
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura and Paulo Nunes',
|
||||
date is 2006/11/26,
|
||||
comment is 'Bisection algorithm.']).
|
||||
|
||||
find_root(Function, A, B, Error, Zero) :-
|
||||
@@ -163,9 +163,9 @@
|
||||
implements(find_rootp)).
|
||||
|
||||
:- info([
|
||||
version is 1.0,
|
||||
date is 2006/4/21,
|
||||
author is 'Paulo Nunes',
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura and Paulo Nunes',
|
||||
date is 2006/11/26,
|
||||
comment is 'Newton algorithm.']).
|
||||
|
||||
find_root(Function, Xa, Xb, Deviation, Zero) :-
|
||||
@@ -203,9 +203,9 @@
|
||||
implements(find_rootp)).
|
||||
|
||||
:- info([
|
||||
version is 1.0,
|
||||
date is 2006/4/21,
|
||||
author is 'Paulo Nunes',
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura and Paulo Nunes',
|
||||
date is 2006/11/26,
|
||||
comment is 'Muller algorithm.']).
|
||||
|
||||
find_root(Function, Xa, Xb, Deviation, Zero) :-
|
||||
|
@@ -1,6 +1,6 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.28.2
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
@@ -1,6 +1,6 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.28.2
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
@@ -27,3 +27,18 @@ X = 1 ;
|
||||
X = 2 ;
|
||||
X = 3 ;
|
||||
no
|
||||
|
||||
|
||||
% make a threaded call by commiting to the first solution found:
|
||||
|
||||
| ?- threaded_once(lists::member(X, [1,2,3])).
|
||||
|
||||
X = _G189
|
||||
yes
|
||||
|
||||
% retrieve through backtracking the goal solution:
|
||||
|
||||
| ?- threaded_exit(lists::member(X, [1,2,3])).
|
||||
|
||||
X = 1 ;
|
||||
no
|
||||
|
12
Logtalk/examples/threads/philosophers/NOTES.txt
Normal file
12
Logtalk/examples/threads/philosophers/NOTES.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
||||
|
||||
To load this example and for sample queries, please see the SCRIPT file.
|
||||
|
||||
This folder contains a Logtalk implementation of the classical "dining
|
||||
philosophers" multi-threading problem.
|
114
Logtalk/examples/threads/philosophers/SCRIPT.txt
Normal file
114
Logtalk/examples/threads/philosophers/SCRIPT.txt
Normal file
@@ -0,0 +1,114 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
||||
|
||||
% start by loading the necessary library support files:
|
||||
|
||||
| ?- logtalk_load(library(random_loader)).
|
||||
...
|
||||
|
||||
|
||||
% now you are ready for loading the example:
|
||||
|
||||
| ?- logtalk_load(philosophers(loader)).
|
||||
...
|
||||
|
||||
|
||||
% five meals for each philosopher, each one spending a maximum of five seconds of continuous thinking or eating:
|
||||
|
||||
| ?- threaded_ignore(p1::run(5, 5)), threaded_ignore(p2::run(5, 5)), threaded_ignore(p3::run(5, 5)), threaded_ignore(p4::run(5, 5)), threaded_ignore(p5::run(5, 5)).
|
||||
|
||||
Yes
|
||||
Philosopher p3 thinking for 1 seconds.
|
||||
Philosopher p1 thinking for 2 seconds.
|
||||
Philosopher p2 thinking for 3 seconds.
|
||||
Philosopher p4 thinking for 4 seconds.
|
||||
Philosopher p5 thinking for 3 seconds.
|
||||
Philosopher p3 eating for 2 seconds with chopsticks cs3 and cs2.
|
||||
Philosopher p1 eating for 3 seconds with chopsticks cs5 and cs1.
|
||||
Philosopher p2 thinking for 3 seconds.
|
||||
Philosopher p3 thinking for 2 seconds.
|
||||
Philosopher p5 thinking for 1 seconds.
|
||||
Philosopher p4 eating for 1 seconds with chopsticks cs4 and cs3.
|
||||
Philosopher p5 thinking for 1 seconds.
|
||||
Philosopher p1 thinking for 3 seconds.
|
||||
Philosopher p4 thinking for 1 seconds.
|
||||
Philosopher p3 eating for 2 seconds with chopsticks cs3 and cs2.
|
||||
Philosopher p5 eating for 2 seconds with chopsticks cs5 and cs4.
|
||||
Philosopher p2 thinking for 3 seconds.
|
||||
Philosopher p4 thinking for 2 seconds.
|
||||
Philosopher p3 thinking for 2 seconds.
|
||||
Philosopher p5 thinking for 1 seconds.
|
||||
Philosopher p1 eating for 3 seconds with chopsticks cs5 and cs1.
|
||||
Philosopher p4 eating for 4 seconds with chopsticks cs4 and cs3.
|
||||
Philosopher p5 thinking for 1 seconds.
|
||||
Philosopher p2 thinking for 1 seconds.
|
||||
Philosopher p3 thinking for 4 seconds.
|
||||
Philosopher p5 thinking for 2 seconds.
|
||||
Philosopher p2 thinking for 4 seconds.
|
||||
Philosopher p1 thinking for 1 seconds.
|
||||
Philosopher p5 thinking for 1 seconds.
|
||||
Philosopher p4 thinking for 4 seconds.
|
||||
Philosopher p1 eating for 1 seconds with chopsticks cs5 and cs1.
|
||||
Philosopher p5 thinking for 3 seconds.
|
||||
Philosopher p3 eating for 2 seconds with chopsticks cs3 and cs2.
|
||||
Philosopher p1 thinking for 3 seconds.
|
||||
Philosopher p2 thinking for 4 seconds.
|
||||
Philosopher p3 thinking for 3 seconds.
|
||||
Philosopher p5 eating for 4 seconds with chopsticks cs5 and cs4.
|
||||
Philosopher p4 thinking for 3 seconds.
|
||||
Philosopher p1 thinking for 4 seconds.
|
||||
Philosopher p2 eating for 1 seconds with chopsticks cs1 and cs2.
|
||||
Philosopher p3 thinking for 3 seconds.
|
||||
Philosopher p4 thinking for 3 seconds.
|
||||
Philosopher p2 thinking for 1 seconds.
|
||||
Philosopher p5 thinking for 2 seconds.
|
||||
Philosopher p2 eating for 3 seconds with chopsticks cs1 and cs2.
|
||||
Philosopher p1 thinking for 4 seconds.
|
||||
Philosopher p3 thinking for 3 seconds.
|
||||
Philosopher p5 eating for 2 seconds with chopsticks cs5 and cs4.
|
||||
Philosopher p4 thinking for 1 seconds.
|
||||
Philosopher p4 thinking for 4 seconds.
|
||||
Philosopher p2 thinking for 1 seconds.
|
||||
Philosopher p5 thinking for 4 seconds.
|
||||
Philosopher p1 eating for 4 seconds with chopsticks cs5 and cs1.
|
||||
Philosopher p2 thinking for 2 seconds.
|
||||
Philosopher p3 eating for 2 seconds with chopsticks cs3 and cs2.
|
||||
Philosopher p2 thinking for 3 seconds.
|
||||
Philosopher p3 thinking for 1 seconds.
|
||||
Philosopher p4 eating for 1 seconds with chopsticks cs4 and cs3.
|
||||
Philosopher p5 thinking for 1 seconds.
|
||||
Philosopher p3 thinking for 4 seconds.
|
||||
Philosopher p4 thinking for 4 seconds.
|
||||
Philosopher p1 thinking for 2 seconds.
|
||||
Philosopher p5 eating for 2 seconds with chopsticks cs5 and cs4.
|
||||
Philosopher p2 eating for 2 seconds with chopsticks cs1 and cs2.
|
||||
Philosopher p1 thinking for 3 seconds.
|
||||
Philosopher p5 thinking for 4 seconds.
|
||||
Philosopher p2 thinking for 2 seconds.
|
||||
Philosopher p3 eating for 4 seconds with chopsticks cs3 and cs2.
|
||||
Philosopher p4 thinking for 2 seconds.
|
||||
Philosopher p1 eating for 3 seconds with chopsticks cs5 and cs1.
|
||||
Philosopher p2 thinking for 1 seconds.
|
||||
Philosopher p4 thinking for 3 seconds.
|
||||
Philosopher p2 thinking for 1 seconds.
|
||||
Philosopher p5 thinking for 3 seconds.
|
||||
p3 terminated.
|
||||
Philosopher p2 thinking for 3 seconds.
|
||||
p1 terminated.
|
||||
Philosopher p4 eating for 3 seconds with chopsticks cs4 and cs3.
|
||||
Philosopher p5 thinking for 4 seconds.
|
||||
Philosopher p2 eating for 4 seconds with chopsticks cs1 and cs2.
|
||||
Philosopher p4 thinking for 4 seconds.
|
||||
Philosopher p5 eating for 1 seconds with chopsticks cs5 and cs4.
|
||||
Philosopher p2 thinking for 1 seconds.
|
||||
p5 terminated.
|
||||
Philosopher p2 eating for 4 seconds with chopsticks cs1 and cs2.
|
||||
Philosopher p4 eating for 3 seconds with chopsticks cs4 and cs3.
|
||||
p4 terminated.
|
||||
p2 terminated.
|
||||
|
13
Logtalk/examples/threads/philosophers/loader.lgt
Normal file
13
Logtalk/examples/threads/philosophers/loader.lgt
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
:- initialization(
|
||||
logtalk_load(
|
||||
philosophers)).
|
||||
|
||||
/*
|
||||
If you intend to use the FOP XSL:FO processor for generating PDF documenting
|
||||
files, comment the directive above and uncomment the directive below
|
||||
|
||||
:- initialization(
|
||||
logtalk_load(
|
||||
philosophers, [xmlsref(standalone)])).
|
||||
*/
|
235
Logtalk/examples/threads/philosophers/philosophers.lgt
Normal file
235
Logtalk/examples/threads/philosophers/philosophers.lgt
Normal file
@@ -0,0 +1,235 @@
|
||||
|
||||
:- category(chopstick).
|
||||
|
||||
:- info([
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura',
|
||||
date is 2006/12/2,
|
||||
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.0,
|
||||
author is 'Paulo Moura',
|
||||
date is 2006/12/2,
|
||||
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']]).
|
||||
|
||||
:- private(random/2).
|
||||
:- synchronized(random/2).
|
||||
:- mode(random(+integer, -integer), one).
|
||||
:- info(random/2, [
|
||||
comment is 'Ensures synchronized access to the random number generator.',
|
||||
argnames is ['Limit', 'Random']]).
|
||||
|
||||
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(MaxTime, ThinkTime),
|
||||
message(['Philosopher ', Philosopher, ' thinking for ', ThinkTime, ' seconds.']),
|
||||
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(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, '.']),
|
||||
sleep(EatTime),
|
||||
::LeftStick::put_down,
|
||||
::RightStick::put_down
|
||||
; ::LeftStick::put_down,
|
||||
fail
|
||||
).
|
||||
|
||||
% as the "random" library object is not multi-threading aware, we must use a
|
||||
% synchronized wrap up predicate (random/2) to call the random number generator:
|
||||
random(Limit, Value) :-
|
||||
random::random(1, Limit, Value).
|
||||
|
||||
% 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.
|
@@ -1,6 +1,6 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.28.2
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
@@ -9,7 +9,11 @@ Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
To load this example and for sample queries, please see the SCRIPT file.
|
||||
|
||||
This folder contains a simple multi-threading example with calculating
|
||||
prime numbers on a given interval. Try to run the example in single and
|
||||
prime numbers in a given interval. Try to run the example in single and
|
||||
multi-processor (or multi-core) computers and compare the results. Most
|
||||
Prolog compilers allows you to measure the time taken for proving a goal
|
||||
using proprietary predicates.
|
||||
|
||||
Note that this example is meant to show how to use Logtalk multi-threading
|
||||
predicates, not to illustrate the best solution for finding primes numbers
|
||||
on a given interval.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.28.2
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
@@ -2,9 +2,9 @@
|
||||
:- object(primes).
|
||||
|
||||
:- info([
|
||||
version is 1.0,
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura',
|
||||
date is 2006/04/14,
|
||||
date is 2006/11/26,
|
||||
comment is 'Simple example for comparing single and multi-threading calculation of prime numbers.']).
|
||||
|
||||
:- threaded.
|
||||
|
19
Logtalk/examples/threads/sync/NOTES.txt
Normal file
19
Logtalk/examples/threads/sync/NOTES.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
||||
|
||||
To load this example and for sample queries, please see the SCRIPT file.
|
||||
|
||||
This folder contains a simple multi-threading example illustrating the
|
||||
use of the "synchronized" predicate directive to cope with methods that
|
||||
have side-effects.
|
||||
|
||||
The object defined in the example source file, "sync.lgt", defines a
|
||||
predicate named waste_time/0 that is used to delay the execuion of goals
|
||||
in order to better illustrate the semantics of the "synchronized" predicate
|
||||
directive. This predicate uses a counter that you might need to adjust,
|
||||
depending on your Prolog compiler and computer performance.
|
57
Logtalk/examples/threads/sync/SCRIPT.txt
Normal file
57
Logtalk/examples/threads/sync/SCRIPT.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
=================================================================
|
||||
Logtalk - Object oriented extension to Prolog
|
||||
Release 2.29.1
|
||||
|
||||
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
|
||||
=================================================================
|
||||
|
||||
|
||||
% start by loading the loading the example:
|
||||
|
||||
| ?- logtalk_load(sync(loader)).
|
||||
...
|
||||
|
||||
|
||||
% send three asynchronous messages whose corresponding methods perform output operations:
|
||||
|
||||
| ?- threaded_ignore(nasty1::io(alpha)), threaded_ignore(nasty1::io(digit)), threaded_ignore(nasty1::io(alpha)).
|
||||
|
||||
a0ab1bc2c3ddefef45gg6hh7ii8jkjk9
|
||||
llmmnnopopqqrrsstztzyyxxwwuv
|
||||
uv
|
||||
|
||||
Yes
|
||||
|
||||
|
||||
% send three asynchronous messages whose corresponding methods perform database updates
|
||||
% (this may or may not work, most likely will throw an exception):
|
||||
|
||||
| ?- threaded_ignore(nasty1::update_db(_)), threaded_ignore(nasty1::update_db(_)), threaded_ignore(nasty1::update_db(_)).
|
||||
|
||||
No
|
||||
|
||||
|
||||
% the best solution is to declare predicates that need to be thread synchronized as "synchronized",
|
||||
% as exemplified in object "nasty2":
|
||||
|
||||
| ?- threaded_ignore(nasty2::io(alpha)), threaded_ignore(nasty2::io(digit)), threaded_ignore(nasty2::io(alpha)).
|
||||
|
||||
abcdefghijklmnopqrstzyxwuv
|
||||
0123456789
|
||||
abcdefghijklmnopqrstzyxwuv
|
||||
|
||||
Yes
|
||||
|
||||
|
||||
| ?- threaded_call(nasty2::update_db(_)), threaded_call(nasty2::update_db(_)), threaded_call(nasty2::update_db(_)).
|
||||
|
||||
Yes
|
||||
|
||||
| ?- threaded_exit(nasty2::update_db(X)), threaded_exit(nasty2::update_db(Y)), threaded_exit(nasty2::update_db(Z)).
|
||||
|
||||
|
||||
X = 1
|
||||
Y = 2
|
||||
Z = 3
|
||||
|
||||
Yes
|
13
Logtalk/examples/threads/sync/loader.lgt
Normal file
13
Logtalk/examples/threads/sync/loader.lgt
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
:- initialization(
|
||||
logtalk_load(
|
||||
sync)).
|
||||
|
||||
/*
|
||||
If you intend to use the FOP XSL:FO processor for generating PDF documenting
|
||||
files, comment the directive above and uncomment the directive below
|
||||
|
||||
:- initialization(
|
||||
logtalk_load(
|
||||
sync, [xmlsref(standalone)])).
|
||||
*/
|
121
Logtalk/examples/threads/sync/sync.lgt
Normal file
121
Logtalk/examples/threads/sync/sync.lgt
Normal file
@@ -0,0 +1,121 @@
|
||||
|
||||
:- object(nasty1).
|
||||
|
||||
:- info([
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura',
|
||||
date is 2006/11/26,
|
||||
comment is 'Simple example for illustrating the problems with lack of thread synchronization when calling methods with side-effects.']).
|
||||
|
||||
:- threaded.
|
||||
|
||||
:- public(update_db/1).
|
||||
:- mode(update_db(-integer), one).
|
||||
:- info(update_db/1, [
|
||||
comment is 'Perform a database update with a long delay between retracting the old information and asserting the new one.',
|
||||
argnames is ['New']]).
|
||||
|
||||
:- private(db/1).
|
||||
:- dynamic(db/1).
|
||||
|
||||
:- public(io/1).
|
||||
:- mode(io(+atom), one).
|
||||
:- info(io/1, [
|
||||
comment is 'Write some characters to the standard output stream with a long delay between each write operation.',
|
||||
argnames is ['Chars']]).
|
||||
|
||||
db(0).
|
||||
|
||||
update_db(New) :-
|
||||
retract(db(Old)),
|
||||
waste_time,
|
||||
New is Old + 1,
|
||||
waste_time,
|
||||
assertz(db(New)).
|
||||
|
||||
io(alpha) :-
|
||||
write(a), waste_time, write(b), waste_time, write(c), waste_time, write(d), waste_time, write(e),
|
||||
write(f), waste_time, write(g), waste_time, write(h), waste_time, write(i), waste_time, write(j),
|
||||
write(k), waste_time, write(l), waste_time, write(m), waste_time, write(n), waste_time, write(o),
|
||||
write(p), waste_time, write(q), waste_time, write(r), waste_time, write(s), waste_time, write(t),
|
||||
write(z), waste_time, write(y), waste_time, write(x), waste_time, write(w), waste_time, write(u),
|
||||
write(v), nl.
|
||||
|
||||
io(digit) :-
|
||||
write(0), waste_time, write(1), waste_time, write(2), waste_time, write(3), waste_time, write(4),
|
||||
write(5), waste_time, write(6), waste_time, write(7), waste_time, write(8), waste_time, write(9), nl.
|
||||
|
||||
waste_time :-
|
||||
between(1, 10000, _),
|
||||
fail.
|
||||
waste_time.
|
||||
|
||||
between(Lower, _, Lower).
|
||||
between(Lower, Upper, Integer) :-
|
||||
Lower < Upper,
|
||||
Next is Lower + 1,
|
||||
between(Next, Upper, Integer).
|
||||
|
||||
:- end_object.
|
||||
|
||||
|
||||
:- object(nasty2).
|
||||
|
||||
:- info([
|
||||
version is 1.1,
|
||||
author is 'Paulo Moura',
|
||||
date is 2006/11/26,
|
||||
comment is 'Simple example for using the "synchronized" predicate directive for multi-threading methods with side-effects.']).
|
||||
|
||||
:- threaded.
|
||||
|
||||
:- public(update_db/1).
|
||||
:- synchronized(update_db/1).
|
||||
:- mode(update_db(-integer), one).
|
||||
:- info(update_db/1, [
|
||||
comment is 'Perform a database update with a long delay between retracting the old information and asserting the new one.',
|
||||
argnames is ['New']]).
|
||||
|
||||
:- private(db/1).
|
||||
:- dynamic(db/1).
|
||||
|
||||
:- public(io/1).
|
||||
:- synchronized(io/1).
|
||||
:- mode(io(+atom), one).
|
||||
:- info(io/1, [
|
||||
comment is 'Write some characters to the standard output stream with a long delay between each write operation.',
|
||||
argnames is ['Chars']]).
|
||||
|
||||
db(0).
|
||||
|
||||
update_db(New) :-
|
||||
retract(db(Old)),
|
||||
waste_time,
|
||||
New is Old + 1,
|
||||
waste_time,
|
||||
assertz(db(New)).
|
||||
|
||||
io(alpha) :-
|
||||
write(a), waste_time, write(b), waste_time, write(c), waste_time, write(d), waste_time, write(e),
|
||||
write(f), waste_time, write(g), waste_time, write(h), waste_time, write(i), waste_time, write(j),
|
||||
write(k), waste_time, write(l), waste_time, write(m), waste_time, write(n), waste_time, write(o),
|
||||
write(p), waste_time, write(q), waste_time, write(r), waste_time, write(s), waste_time, write(t),
|
||||
write(z), waste_time, write(y), waste_time, write(x), waste_time, write(w), waste_time, write(u),
|
||||
write(v), nl.
|
||||
|
||||
io(digit) :-
|
||||
write(0), waste_time, write(1), waste_time, write(2), waste_time, write(3), waste_time, write(4),
|
||||
write(5), waste_time, write(6), waste_time, write(7), waste_time, write(8), waste_time, write(9), nl.
|
||||
|
||||
waste_time :-
|
||||
between(1, 100000, _),
|
||||
fail.
|
||||
waste_time.
|
||||
|
||||
between(Lower, _, Lower).
|
||||
between(Lower, Upper, Integer) :-
|
||||
Lower < Upper,
|
||||
Next is Lower + 1,
|
||||
between(Next, Upper, Integer).
|
||||
|
||||
:- end_object.
|
Reference in New Issue
Block a user