Skip to content

Commit

Permalink
Add futures example (a common concurrent programming idiom)
Browse files Browse the repository at this point in the history
  • Loading branch information
pmoura committed Feb 14, 2019
1 parent 32f3f26 commit 3c6368c
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 2 deletions.
3 changes: 3 additions & 0 deletions RELEASE_NOTES.md
Expand Up @@ -80,6 +80,9 @@ example.

* ADDED: An alternative implementation of the `cascade` example using DCGs.

* ADDED: Simple example of working with "futures", a common concurrent
programming idiom, using the high-level multi-threading predicates.

IDEs, text editors, and syntax highlighters support
---------------------------------------------------

Expand Down
4 changes: 4 additions & 0 deletions examples/NOTES.md
Expand Up @@ -200,6 +200,10 @@ Follows a short description of each included example (in alphabetical order):
alternative version of the `family` example using a family registry
implemented using multifile predicates to avoid dynamic binding

- `futures`
simple example of working with futures, a common concurrent programming
idiom, using the high-level multi-threading predicates

- `hailstone`
example of computing Hailstone sequences

Expand Down
28 changes: 28 additions & 0 deletions examples/futures/NOTES.md
@@ -0,0 +1,28 @@
________________________________________________________________________

This file is part of Logtalk <https://logtalk.org/>
Copyright 1998-2019 Paulo Moura <pmoura@logtalk.org>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
________________________________________________________________________


To load this example and for sample queries, please see the `SCRIPT.txt`
file.

This is a simple example of defining and using futures, a common concurrent
programming idiom. A future is used to represent a term that may not yet be
available due to a pending asynchronous computation. Futures are supported
in Logtalk using its high-level multi-threading features. This example uses
computations over lists as representative of long running operations that
would benefit from asynchronous calls.
39 changes: 39 additions & 0 deletions examples/futures/SCRIPT.txt
@@ -0,0 +1,39 @@
________________________________________________________________________

This file is part of Logtalk <https://logtalk.org/>
Copyright 1998-2019 Paulo Moura <pmoura@logtalk.org>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
________________________________________________________________________


% start by loading the example:

| ?- logtalk_load(futures(loader)).
...


% use the asynchronous calls based predicate definition:

| ?- integer::sequence(1,100,List1), integer::sequence(101,200,List2), list_math::product_sum(List1,List2,Result).

Result = 76002500
yes


% use the threaded engines based predicate definition:

| ?- integer::sequence(1,100,List1), integer::sequence(101,200,List2), list_math::product_sum_engines(List1,List2,Result).

Result = 76002500
yes
65 changes: 65 additions & 0 deletions examples/futures/futures.lgt
@@ -0,0 +1,65 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This file is part of Logtalk <https://logtalk.org/>
% Copyright 1998-2019 Paulo Moura <pmoura@logtalk.org>
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


:- object(list_math).

:- info([
version is 1.0,
author is 'Paulo Moura',
date is 2019/02/14,
comment is 'Simple futures programming idiom example.'
]).

:- threaded.

:- public([
product_sum/3, product_sum_engines/3
]).

:- uses(numberlist, [sum/2]).

% the first alternative uses asynchronous calls but incurs a performance
% penalty due to unification of the lists when retrieving the results

product_sum(List1, List2, Result) :-
% asynchronous calls (will run concurrently)
threaded_once(sum(List1, Sum1)),
threaded_once(sum(List2, Sum2)),
% get results (block until available)
threaded_exit(sum(List1, Sum1)),
threaded_exit(sum(List2, Sum2)),
Result is Sum1 * Sum2.

% the second alternative uses threaded engines and unifies only the
% resulting sums when retrieving the results

product_sum_engines(List1, List2, Result) :-
% engines prove goals concurrently
threaded_engine_create(Sum1, sum(List1, Sum1), Engine1),
threaded_engine_create(Sum2, sum(List2, Sum2), Engine2),
% get results (block until available)
threaded_engine_next(Engine1, Sum1),
threaded_engine_next(Engine2, Sum2),
Result is Sum1 * Sum2,
% dispose of the engines
threaded_engine_destroy(Engine1),
threaded_engine_destroy(Engine2).

:- end_object.
32 changes: 32 additions & 0 deletions examples/futures/loader.lgt
@@ -0,0 +1,32 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This file is part of Logtalk <https://logtalk.org/>
% Copyright 1998-2019 Paulo Moura <pmoura@logtalk.org>
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


:- if((current_logtalk_flag(threads, supported), current_logtalk_flag(engines, supported))).

:- initialization((
logtalk_load(library(types_loader)),
logtalk_load(futures, [optimize(on)])
)).

:- else.

:- initialization((write('WARNING: example not supported on this backend Prolog compiler!'), nl)).

:- endif.
38 changes: 38 additions & 0 deletions examples/futures/tester.lgt
@@ -0,0 +1,38 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This file is part of Logtalk <https://logtalk.org/>
% Copyright 1998-2019 Paulo Moura <pmoura@logtalk.org>
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


:- if((current_logtalk_flag(threads, supported), current_logtalk_flag(engines, supported))).

:- initialization((
set_logtalk_flag(report, warnings),
logtalk_load(library(types_loader)),
logtalk_load(lgtunit(loader)),
logtalk_load(futures, [source_data(on), debug(on)]),
logtalk_load(tests, [hook(lgtunit)]),
tests::run
)).

:- else.

:- initialization((
write('(not applicable)'), nl
)).

:- endif.
45 changes: 45 additions & 0 deletions examples/futures/tests.lgt
@@ -0,0 +1,45 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This file is part of Logtalk <https://logtalk.org/>
% Copyright 1998-2019 Paulo Moura <pmoura@logtalk.org>
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


:- object(tests,
extends(lgtunit)).

:- info([
version is 1.0,
author is 'Paulo Moura',
date is 2019/02/14,
comment is 'Unit tests for the "futures" example.'
]).

cover(list_math).

test(futures_01) :-
integer::sequence(1, 100, List1),
integer::sequence(101, 200, List2),
list_math::product_sum(List1, List2, Result),
Result == 76002500.

test(futures_02) :-
integer::sequence(1, 100, List1),
integer::sequence(101, 200, List2),
list_math::product_sum_engines(List1, List2, Result),
Result == 76002500.

:- end_object.
3 changes: 2 additions & 1 deletion paths/paths.pl
@@ -1,7 +1,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Default library paths
% Last updated on January 22, 2019
% Last updated on February 14, 2019
%
% This file is part of Logtalk <https://logtalk.org/>
% Copyright 1998-2019 Paulo Moura <pmoura@logtalk.org>
Expand Down Expand Up @@ -153,6 +153,7 @@
logtalk_library_path(fibonacci, threads('fibonacci/')).
logtalk_library_path(fluents, engines('fluents/')).
logtalk_library_path(functions, threads('functions/')).
logtalk_library_path(futures, examples('futures/')).
logtalk_library_path(hailstone, examples('hailstone/')).
logtalk_library_path(hanoi, threads('hanoi/')).
logtalk_library_path(hello_world, examples('hello_world/')).
Expand Down
3 changes: 2 additions & 1 deletion paths/paths_examples.pl
@@ -1,7 +1,7 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Default library paths for the programming examples
% Last updated on January 22, 2019
% Last updated on February 14, 2019
%
% This file is part of Logtalk <https://logtalk.org/>
% Copyright 1998-2019 Paulo Moura <pmoura@logtalk.org>
Expand Down Expand Up @@ -89,6 +89,7 @@
logtalk_library_path(fibonacci, threads('fibonacci/')).
logtalk_library_path(fluents, engines('fluents/')).
logtalk_library_path(functions, threads('functions/')).
logtalk_library_path(futures, examples('futures/')).
logtalk_library_path(hailstone, examples('hailstone/')).
logtalk_library_path(hanoi, threads('hanoi/')).
logtalk_library_path(hello_world, examples('hello_world/')).
Expand Down

0 comments on commit 3c6368c

Please sign in to comment.