aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/Makefile2
-rw-r--r--lib/stdlib/doc/src/Makefile3
-rw-r--r--lib/stdlib/doc/src/array.xml2
-rw-r--r--lib/stdlib/doc/src/base64.xml2
-rw-r--r--lib/stdlib/doc/src/binary.xml4
-rw-r--r--lib/stdlib/doc/src/book.xml2
-rw-r--r--lib/stdlib/doc/src/c.xml2
-rw-r--r--lib/stdlib/doc/src/calendar.xml2
-rw-r--r--lib/stdlib/doc/src/dets.xml2
-rw-r--r--lib/stdlib/doc/src/dict.xml2
-rw-r--r--lib/stdlib/doc/src/digraph.xml2
-rw-r--r--lib/stdlib/doc/src/digraph_utils.xml2
-rw-r--r--lib/stdlib/doc/src/epp.xml2
-rw-r--r--lib/stdlib/doc/src/erl_eval.xml2
-rw-r--r--lib/stdlib/doc/src/erl_expand_records.xml2
-rw-r--r--lib/stdlib/doc/src/erl_id_trans.xml2
-rw-r--r--lib/stdlib/doc/src/erl_internal.xml2
-rw-r--r--lib/stdlib/doc/src/erl_lint.xml2
-rw-r--r--lib/stdlib/doc/src/erl_pp.xml2
-rw-r--r--lib/stdlib/doc/src/erl_tar.xml2
-rw-r--r--lib/stdlib/doc/src/ets.xml4
-rw-r--r--lib/stdlib/doc/src/file_sorter.xml2
-rw-r--r--lib/stdlib/doc/src/filelib.xml2
-rw-r--r--lib/stdlib/doc/src/filename.xml2
-rw-r--r--lib/stdlib/doc/src/gen_event.xml2
-rw-r--r--lib/stdlib/doc/src/gen_fsm.xml16
-rw-r--r--lib/stdlib/doc/src/gen_server.xml3
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml1724
-rw-r--r--lib/stdlib/doc/src/io.xml2
-rw-r--r--lib/stdlib/doc/src/io_lib.xml2
-rw-r--r--lib/stdlib/doc/src/io_protocol.xml2
-rw-r--r--lib/stdlib/doc/src/lib.xml2
-rw-r--r--lib/stdlib/doc/src/lists.xml17
-rw-r--r--lib/stdlib/doc/src/log_mf_h.xml2
-rw-r--r--lib/stdlib/doc/src/maps.xml62
-rw-r--r--lib/stdlib/doc/src/math.xml2
-rw-r--r--lib/stdlib/doc/src/ms_transform.xml2
-rw-r--r--lib/stdlib/doc/src/notes.xml2
-rw-r--r--lib/stdlib/doc/src/notes_history.xml2
-rw-r--r--lib/stdlib/doc/src/ordsets.xml2
-rw-r--r--lib/stdlib/doc/src/part.xml2
-rw-r--r--lib/stdlib/doc/src/part_notes.xml2
-rw-r--r--lib/stdlib/doc/src/part_notes_history.xml2
-rw-r--r--lib/stdlib/doc/src/pool.xml2
-rw-r--r--lib/stdlib/doc/src/proc_lib.xml8
-rw-r--r--lib/stdlib/doc/src/proplists.xml2
-rw-r--r--lib/stdlib/doc/src/qlc.xml2
-rw-r--r--lib/stdlib/doc/src/queue.xml2
-rw-r--r--lib/stdlib/doc/src/random.xml2
-rw-r--r--lib/stdlib/doc/src/re.xml2
-rw-r--r--lib/stdlib/doc/src/ref_man.xml3
-rw-r--r--lib/stdlib/doc/src/shell.xml2
-rw-r--r--lib/stdlib/doc/src/shell_default.xml2
-rw-r--r--lib/stdlib/doc/src/slave.xml2
-rw-r--r--lib/stdlib/doc/src/sofs.xml2
-rw-r--r--lib/stdlib/doc/src/specs.xml1
-rw-r--r--lib/stdlib/doc/src/stdlib_app.xml2
-rw-r--r--lib/stdlib/doc/src/string.xml2
-rw-r--r--lib/stdlib/doc/src/supervisor.xml10
-rw-r--r--lib/stdlib/doc/src/supervisor_bridge.xml2
-rw-r--r--lib/stdlib/doc/src/sys.xml31
-rw-r--r--lib/stdlib/doc/src/timer.xml2
-rw-r--r--lib/stdlib/doc/src/unicode.xml2
-rw-r--r--lib/stdlib/doc/src/unicode_usage.xml2
-rw-r--r--lib/stdlib/doc/src/win32reg.xml2
-rw-r--r--lib/stdlib/doc/src/zip.xml2
-rw-r--r--lib/stdlib/examples/erl_id_trans.erl4
-rw-r--r--lib/stdlib/include/assert.hrl31
-rw-r--r--lib/stdlib/include/erl_compile.hrl2
-rw-r--r--lib/stdlib/include/ms_transform.hrl2
-rw-r--r--lib/stdlib/include/qlc.hrl2
-rw-r--r--lib/stdlib/include/zip.hrl2
-rw-r--r--lib/stdlib/src/Makefile3
-rw-r--r--lib/stdlib/src/array.erl2
-rw-r--r--lib/stdlib/src/base64.erl2
-rw-r--r--lib/stdlib/src/binary.erl2
-rw-r--r--lib/stdlib/src/c.erl2
-rw-r--r--lib/stdlib/src/calendar.erl2
-rw-r--r--lib/stdlib/src/dets.hrl2
-rw-r--r--lib/stdlib/src/dets_server.erl2
-rw-r--r--lib/stdlib/src/dets_sup.erl2
-rw-r--r--lib/stdlib/src/digraph_utils.erl2
-rw-r--r--lib/stdlib/src/edlin.erl2
-rw-r--r--lib/stdlib/src/edlin_expand.erl2
-rw-r--r--lib/stdlib/src/epp.erl7
-rw-r--r--lib/stdlib/src/erl_bits.erl2
-rw-r--r--lib/stdlib/src/erl_compile.erl2
-rw-r--r--lib/stdlib/src/erl_internal.erl2
-rw-r--r--lib/stdlib/src/erl_lint.erl108
-rw-r--r--lib/stdlib/src/erl_parse.yrl12
-rw-r--r--lib/stdlib/src/erl_posix_msg.erl2
-rw-r--r--lib/stdlib/src/erl_pp.erl26
-rw-r--r--lib/stdlib/src/erl_tar.erl2
-rw-r--r--lib/stdlib/src/error_logger_file_h.erl2
-rw-r--r--lib/stdlib/src/error_logger_tty_h.erl2
-rw-r--r--lib/stdlib/src/ets.erl2
-rw-r--r--lib/stdlib/src/eval_bits.erl2
-rw-r--r--lib/stdlib/src/filelib.erl2
-rw-r--r--lib/stdlib/src/filename.erl2
-rw-r--r--lib/stdlib/src/gen.erl121
-rw-r--r--lib/stdlib/src/gen_event.erl11
-rw-r--r--lib/stdlib/src/gen_fsm.erl85
-rw-r--r--lib/stdlib/src/gen_server.erl112
-rw-r--r--lib/stdlib/src/gen_statem.erl1267
-rw-r--r--lib/stdlib/src/io_lib.erl18
-rw-r--r--lib/stdlib/src/io_lib_format.erl2
-rw-r--r--lib/stdlib/src/io_lib_fread.erl2
-rw-r--r--lib/stdlib/src/io_lib_pretty.erl2
-rw-r--r--lib/stdlib/src/lib.erl2
-rw-r--r--lib/stdlib/src/lists.erl15
-rw-r--r--lib/stdlib/src/log_mf_h.erl2
-rw-r--r--lib/stdlib/src/maps.erl61
-rw-r--r--lib/stdlib/src/math.erl2
-rw-r--r--lib/stdlib/src/ordsets.erl2
-rw-r--r--lib/stdlib/src/otp_internal.erl119
-rw-r--r--lib/stdlib/src/pool.erl2
-rw-r--r--lib/stdlib/src/proc_lib.erl20
-rw-r--r--lib/stdlib/src/proplists.erl2
-rw-r--r--lib/stdlib/src/queue.erl2
-rw-r--r--lib/stdlib/src/rand.erl10
-rw-r--r--lib/stdlib/src/random.erl2
-rw-r--r--lib/stdlib/src/re.erl2
-rw-r--r--lib/stdlib/src/sets.erl2
-rw-r--r--lib/stdlib/src/shell_default.erl2
-rw-r--r--lib/stdlib/src/slave.erl2
-rw-r--r--lib/stdlib/src/sofs.erl2
-rw-r--r--lib/stdlib/src/stdlib.app.src3
-rw-r--r--lib/stdlib/src/stdlib.appup.src2
-rw-r--r--lib/stdlib/src/string.erl2
-rw-r--r--lib/stdlib/src/supervisor.erl6
-rw-r--r--lib/stdlib/src/supervisor_bridge.erl2
-rw-r--r--lib/stdlib/src/sys.erl2
-rw-r--r--lib/stdlib/src/timer.erl2
-rw-r--r--lib/stdlib/src/win32reg.erl2
-rw-r--r--lib/stdlib/test/ExpandTestCaps.erl2
-rw-r--r--lib/stdlib/test/ExpandTestCaps1.erl2
-rw-r--r--lib/stdlib/test/Makefile1
-rw-r--r--lib/stdlib/test/array_SUITE.erl2
-rw-r--r--lib/stdlib/test/base64_SUITE.erl2
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl2
-rw-r--r--lib/stdlib/test/binary_module_SUITE.erl2
-rw-r--r--lib/stdlib/test/c_SUITE.erl2
-rw-r--r--lib/stdlib/test/c_SUITE_data/m.erl2
-rw-r--r--lib/stdlib/test/calendar_SUITE.erl2
-rw-r--r--lib/stdlib/test/dict_SUITE.erl2
-rw-r--r--lib/stdlib/test/digraph_SUITE.erl2
-rw-r--r--lib/stdlib/test/digraph_utils_SUITE.erl2
-rw-r--r--lib/stdlib/test/dummy1_h.erl2
-rw-r--r--lib/stdlib/test/dummy_h.erl2
-rw-r--r--lib/stdlib/test/edlin_expand_SUITE.erl2
-rw-r--r--lib/stdlib/test/epp_SUITE.erl2
-rw-r--r--lib/stdlib/test/epp_SUITE_data/mac.erl2
-rw-r--r--lib/stdlib/test/epp_SUITE_data/mac2.erl2
-rw-r--r--lib/stdlib/test/epp_SUITE_data/mac3.erl2
-rw-r--r--lib/stdlib/test/epp_SUITE_data/pmod.erl2
-rw-r--r--lib/stdlib/test/epp_SUITE_data/variable_1.erl2
-rw-r--r--lib/stdlib/test/epp_SUITE_data/variable_1_include.hrl2
-rw-r--r--lib/stdlib/test/epp_SUITE_data/variable_1_include_dir.hrl2
-rw-r--r--lib/stdlib/test/erl_anno_SUITE.erl2
-rw-r--r--lib/stdlib/test/erl_expand_records_SUITE.erl2
-rw-r--r--lib/stdlib/test/erl_internal_SUITE.erl2
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl163
-rw-r--r--lib/stdlib/test/erl_lint_SUITE_data/format.erl2
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl25
-rw-r--r--lib/stdlib/test/erl_scan_SUITE.erl2
-rw-r--r--lib/stdlib/test/error_logger_forwarder.erl8
-rw-r--r--lib/stdlib/test/error_logger_h_SUITE.erl21
-rw-r--r--lib/stdlib/test/escript_SUITE.erl2
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict.erl2
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_app.erl2
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_sup.erl2
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy.erl2
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_app.erl2
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_sup.erl2
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main.erl2
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl2
-rw-r--r--lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl2
-rw-r--r--lib/stdlib/test/ets_SUITE.erl2
-rw-r--r--lib/stdlib/test/ets_tough_SUITE.erl2
-rw-r--r--lib/stdlib/test/expand_test.erl2
-rw-r--r--lib/stdlib/test/expand_test1.erl2
-rw-r--r--lib/stdlib/test/file_sorter_SUITE.erl2
-rw-r--r--lib/stdlib/test/filelib_SUITE.erl2
-rw-r--r--lib/stdlib/test/filename_SUITE.erl2
-rw-r--r--lib/stdlib/test/fixtable_SUITE.erl2
-rw-r--r--lib/stdlib/test/format_SUITE.erl2
-rw-r--r--lib/stdlib/test/gen_event_SUITE.erl2
-rw-r--r--lib/stdlib/test/gen_fsm_SUITE.erl12
-rw-r--r--lib/stdlib/test/gen_server_SUITE.erl2
-rw-r--r--lib/stdlib/test/gen_statem_SUITE.erl1578
-rw-r--r--lib/stdlib/test/id_transform_SUITE.erl2
-rw-r--r--lib/stdlib/test/id_transform_SUITE_data/External.hrl2
-rw-r--r--lib/stdlib/test/id_transform_SUITE_data/m.hrl2
-rw-r--r--lib/stdlib/test/id_transform_SUITE_data/m_i.hrl2
-rw-r--r--lib/stdlib/test/id_transform_SUITE_data/oe_ex.hrl2
-rw-r--r--lib/stdlib/test/io_SUITE.erl2
-rw-r--r--lib/stdlib/test/io_proto_SUITE.erl2
-rw-r--r--lib/stdlib/test/lists_SUITE.erl18
-rw-r--r--lib/stdlib/test/log_mf_h_SUITE.erl2
-rw-r--r--lib/stdlib/test/maps_SUITE.erl56
-rw-r--r--lib/stdlib/test/ms_transform_SUITE.erl2
-rw-r--r--lib/stdlib/test/naughty_child.erl2
-rw-r--r--lib/stdlib/test/proc_lib_SUITE.erl2
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl2
-rw-r--r--lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl2
-rw-r--r--lib/stdlib/test/queue_SUITE.erl2
-rw-r--r--lib/stdlib/test/rand_SUITE.erl4
-rw-r--r--lib/stdlib/test/random_SUITE.erl2
-rw-r--r--lib/stdlib/test/random_iolist.erl2
-rw-r--r--lib/stdlib/test/random_unicode_list.erl2
-rw-r--r--lib/stdlib/test/re_SUITE.erl2
-rw-r--r--lib/stdlib/test/re_testoutput1_replacement_test.erl2
-rw-r--r--lib/stdlib/test/re_testoutput1_split_test.erl2
-rw-r--r--lib/stdlib/test/run_pcre_tests.erl2
-rw-r--r--lib/stdlib/test/select_SUITE.erl2
-rw-r--r--lib/stdlib/test/sets_SUITE.erl2
-rw-r--r--lib/stdlib/test/shell_SUITE.erl2
-rw-r--r--lib/stdlib/test/slave_SUITE.erl2
-rw-r--r--lib/stdlib/test/sofs_SUITE.erl2
-rw-r--r--lib/stdlib/test/stdlib_SUITE.erl2
-rw-r--r--lib/stdlib/test/string_SUITE.erl2
-rw-r--r--lib/stdlib/test/supervisor_1.erl2
-rw-r--r--lib/stdlib/test/supervisor_2.erl2
-rw-r--r--lib/stdlib/test/supervisor_3.erl2
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl2
-rw-r--r--lib/stdlib/test/supervisor_bridge_SUITE.erl2
-rw-r--r--lib/stdlib/test/sys_SUITE.erl2
-rw-r--r--lib/stdlib/test/sys_sp1.erl2
-rw-r--r--lib/stdlib/test/sys_sp2.erl2
-rw-r--r--lib/stdlib/test/tar_SUITE.erl2
-rw-r--r--lib/stdlib/test/timer_SUITE.erl2
-rw-r--r--lib/stdlib/test/timer_simple_SUITE.erl2
-rw-r--r--lib/stdlib/test/unicode_SUITE.erl2
-rw-r--r--lib/stdlib/test/win32reg_SUITE.erl2
-rw-r--r--lib/stdlib/test/y2k_SUITE.erl2
-rw-r--r--lib/stdlib/test/zip_SUITE.erl2
-rw-r--r--lib/stdlib/vsn.mk2
237 files changed, 5463 insertions, 736 deletions
diff --git a/lib/stdlib/Makefile b/lib/stdlib/Makefile
index 563a2defa2..3086d85445 100644
--- a/lib/stdlib/Makefile
+++ b/lib/stdlib/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2009. All Rights Reserved.
+# Copyright Ericsson AB 1996-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/doc/src/Makefile b/lib/stdlib/doc/src/Makefile
index 196c86748f..26602764a6 100644
--- a/lib/stdlib/doc/src/Makefile
+++ b/lib/stdlib/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2015. All Rights Reserved.
+# Copyright Ericsson AB 1997-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -68,6 +68,7 @@ XML_REF3_FILES = \
gen_event.xml \
gen_fsm.xml \
gen_server.xml \
+ gen_statem.xml \
io.xml \
io_lib.xml \
lib.xml \
diff --git a/lib/stdlib/doc/src/array.xml b/lib/stdlib/doc/src/array.xml
index 0f33e2621c..bff98245bf 100644
--- a/lib/stdlib/doc/src/array.xml
+++ b/lib/stdlib/doc/src/array.xml
@@ -3,7 +3,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2014</year>
+ <year>2007</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/base64.xml b/lib/stdlib/doc/src/base64.xml
index 276d28e174..7b82d7dd3d 100644
--- a/lib/stdlib/doc/src/base64.xml
+++ b/lib/stdlib/doc/src/base64.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2013</year>
+ <year>2007</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml
index 2682198fe5..933157fc34 100644
--- a/lib/stdlib/doc/src/binary.xml
+++ b/lib/stdlib/doc/src/binary.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2014</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -366,7 +366,7 @@
<code>
1> binary:matches(&lt;&lt;"abcde"&gt;&gt;,
- [&lt;&lt;"bcde"&gt;&gt;,&lt;&lt;"bc"&gt;&gt;>,&lt;&lt;"de"&gt;&gt;],[]).
+ [&lt;&lt;"bcde"&gt;&gt;,&lt;&lt;"bc"&gt;&gt;,&lt;&lt;"de"&gt;&gt;],[]).
[{1,4}]
</code>
diff --git a/lib/stdlib/doc/src/book.xml b/lib/stdlib/doc/src/book.xml
index 043f6cc19b..84ce3f0788 100644
--- a/lib/stdlib/doc/src/book.xml
+++ b/lib/stdlib/doc/src/book.xml
@@ -4,7 +4,7 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/c.xml b/lib/stdlib/doc/src/c.xml
index e5238fa7db..9b4a9489c0 100644
--- a/lib/stdlib/doc/src/c.xml
+++ b/lib/stdlib/doc/src/c.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml
index 853184dc0f..38bf55679e 100644
--- a/lib/stdlib/doc/src/calendar.xml
+++ b/lib/stdlib/doc/src/calendar.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/dets.xml b/lib/stdlib/doc/src/dets.xml
index 48400733d1..177c2ba508 100644
--- a/lib/stdlib/doc/src/dets.xml
+++ b/lib/stdlib/doc/src/dets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/dict.xml b/lib/stdlib/doc/src/dict.xml
index e10531caac..20bab99a9c 100644
--- a/lib/stdlib/doc/src/dict.xml
+++ b/lib/stdlib/doc/src/dict.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml
index 291be6c08b..16dd789caf 100644
--- a/lib/stdlib/doc/src/digraph.xml
+++ b/lib/stdlib/doc/src/digraph.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/digraph_utils.xml b/lib/stdlib/doc/src/digraph_utils.xml
index 639069543c..9bddee546f 100644
--- a/lib/stdlib/doc/src/digraph_utils.xml
+++ b/lib/stdlib/doc/src/digraph_utils.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2013</year>
+ <year>2000</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/epp.xml b/lib/stdlib/doc/src/epp.xml
index 8c901f57ec..0802f0e47c 100644
--- a/lib/stdlib/doc/src/epp.xml
+++ b/lib/stdlib/doc/src/epp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/erl_eval.xml b/lib/stdlib/doc/src/erl_eval.xml
index ba988e7ca2..d60b04b510 100644
--- a/lib/stdlib/doc/src/erl_eval.xml
+++ b/lib/stdlib/doc/src/erl_eval.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/erl_expand_records.xml b/lib/stdlib/doc/src/erl_expand_records.xml
index 497b371434..93e464c733 100644
--- a/lib/stdlib/doc/src/erl_expand_records.xml
+++ b/lib/stdlib/doc/src/erl_expand_records.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2005</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/erl_id_trans.xml b/lib/stdlib/doc/src/erl_id_trans.xml
index 30eb213493..153bd4148e 100644
--- a/lib/stdlib/doc/src/erl_id_trans.xml
+++ b/lib/stdlib/doc/src/erl_id_trans.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/erl_internal.xml b/lib/stdlib/doc/src/erl_internal.xml
index e1ee50b424..940f8c5b40 100644
--- a/lib/stdlib/doc/src/erl_internal.xml
+++ b/lib/stdlib/doc/src/erl_internal.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/erl_lint.xml b/lib/stdlib/doc/src/erl_lint.xml
index 318cb5ac19..3747b0f3c3 100644
--- a/lib/stdlib/doc/src/erl_lint.xml
+++ b/lib/stdlib/doc/src/erl_lint.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/erl_pp.xml b/lib/stdlib/doc/src/erl_pp.xml
index 4b8a571c81..e96fd576ec 100644
--- a/lib/stdlib/doc/src/erl_pp.xml
+++ b/lib/stdlib/doc/src/erl_pp.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/erl_tar.xml b/lib/stdlib/doc/src/erl_tar.xml
index 898b55df72..1f4a43f622 100644
--- a/lib/stdlib/doc/src/erl_tar.xml
+++ b/lib/stdlib/doc/src/erl_tar.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2013</year>
+ <year>2003</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index 447fe51130..2d69c201bc 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1621,6 +1621,8 @@ true</pre>
if the match_spec does not match the object <c><anno>Tuple</anno></c>.</p>
<p>This is a useful debugging and test tool, especially when
writing complicated <c>ets:select/2</c> calls.</p>
+ <p>See also: <seealso marker="erts:erlang#match_spec_test/3">
+ erlang:match_spec_test/3</seealso>.</p>
</desc>
</func>
<func>
diff --git a/lib/stdlib/doc/src/file_sorter.xml b/lib/stdlib/doc/src/file_sorter.xml
index f033eebec7..bc24f02a99 100644
--- a/lib/stdlib/doc/src/file_sorter.xml
+++ b/lib/stdlib/doc/src/file_sorter.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2013</year>
+ <year>2001</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/filelib.xml b/lib/stdlib/doc/src/filelib.xml
index 2cf9490f4b..3ad159a66d 100644
--- a/lib/stdlib/doc/src/filelib.xml
+++ b/lib/stdlib/doc/src/filelib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2003</year><year>2013</year>
+ <year>2003</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml
index ce6aba3657..f284a7596c 100644
--- a/lib/stdlib/doc/src/filename.xml
+++ b/lib/stdlib/doc/src/filename.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2013</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml
index c4bab45781..b2c482d3ed 100644
--- a/lib/stdlib/doc/src/gen_event.xml
+++ b/lib/stdlib/doc/src/gen_event.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/gen_fsm.xml b/lib/stdlib/doc/src/gen_fsm.xml
index 4d594b8eb2..835e252704 100644
--- a/lib/stdlib/doc/src/gen_fsm.xml
+++ b/lib/stdlib/doc/src/gen_fsm.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,12 +31,23 @@
<module>gen_fsm</module>
<modulesummary>Generic Finite State Machine Behaviour</modulesummary>
<description>
+ <note>
+ <p>
+ There is a new behaviour
+ <seealso marker="gen_statem"><c>gen_statem</c></seealso>
+ that is intended to replace <c>gen_fsm</c> for new code.
+ It has the same features and add some really useful.
+ This module will not be removed for the foreseeable future
+ to keep old state machine implementations running.
+ </p>
+ </note>
<p>A behaviour module for implementing a finite state machine.
A generic finite state machine process (gen_fsm) implemented
using this module will have a standard set of interface functions
and include functionality for tracing and error reporting. It will
also fit into an OTP supervision tree. Refer to
- <seealso marker="doc/design_principles:fsm">OTP Design Principles</seealso> for more information.</p>
+ <seealso marker="doc/design_principles:fsm">OTP Design Principles</seealso> for more information.
+ </p>
<p>A gen_fsm assumes all specific parts to be located in a callback
module exporting a pre-defined set of functions. The relationship
between the behaviour functions and the callback functions can be
@@ -848,6 +859,7 @@ gen_fsm:sync_send_all_state_event -----> Module:handle_sync_event/4
<title>SEE ALSO</title>
<p><seealso marker="gen_event">gen_event(3)</seealso>,
<seealso marker="gen_server">gen_server(3)</seealso>,
+ <seealso marker="gen_statem">gen_statem(3)</seealso>,
<seealso marker="supervisor">supervisor(3)</seealso>,
<seealso marker="proc_lib">proc_lib(3)</seealso>,
<seealso marker="sys">sys(3)</seealso></p>
diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml
index 6d04771cd4..10dc978afc 100644
--- a/lib/stdlib/doc/src/gen_server.xml
+++ b/lib/stdlib/doc/src/gen_server.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -715,6 +715,7 @@ gen_server:abcast -----> Module:handle_cast/2
<title>SEE ALSO</title>
<p><seealso marker="gen_event">gen_event(3)</seealso>,
<seealso marker="gen_fsm">gen_fsm(3)</seealso>,
+ <seealso marker="gen_statem">gen_statem(3)</seealso>,
<seealso marker="supervisor">supervisor(3)</seealso>,
<seealso marker="proc_lib">proc_lib(3)</seealso>,
<seealso marker="sys">sys(3)</seealso></p>
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
new file mode 100644
index 0000000000..ec7f267c64
--- /dev/null
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -0,0 +1,1724 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2016</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ 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.
+
+ </legalnotice>
+
+ <title>gen_statem</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ </header>
+ <module>gen_statem</module>
+ <modulesummary>Generic State Machine Behaviour</modulesummary>
+ <description>
+ <p>
+ A behaviour module for implementing a state machine. Two
+ <seealso marker="#type-callback_mode"><em>callback modes</em></seealso>
+ are supported. One for finite state machines
+ (<seealso marker="gen_fsm"><c>gen_fsm</c></seealso> like)
+ that requires the state to be an atom and uses that state as
+ the name of the current callback function,
+ and one without restriction on the state data type
+ that uses one callback function for all states.
+ </p>
+ <p>
+ This is a new behaviour in OTP-19.0.
+ It has been thoroughly reviewed, is stable enough
+ to be used by at least two heavy OTP applications, and is here to stay.
+ But depending on user feedback, we do not expect
+ but might find it necessary to make minor
+ not backwards compatible changes into OTP-20.0,
+ so its state can be designated as "not quite experimental"...
+ </p>
+ <p>
+ The <c>gen_statem</c> behaviour is intended to replace
+ <seealso marker="gen_fsm"><c>gen_fsm</c></seealso> for new code.
+ It has the same features and add some really useful:
+ </p>
+ <list type="bulleted">
+ <item>State code is gathered</item>
+ <item>The state can be any term</item>
+ <item>Events can be postponed</item>
+ <item>Events can be self generated</item>
+ <item>A reply can be sent from a later state</item>
+ <item>There can be multiple sys traceable replies</item>
+ </list>
+ <p>
+ The callback model(s) for <c>gen_statem</c> differs from
+ the one for <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>,
+ but it is still fairly easy to rewrite
+ from <c>gen_fsm</c> to <c>gen_statem</c>.
+ </p>
+ <p>
+ A generic state machine process (<c>gen_statem</c>) implemented
+ using this module will have a standard set of interface functions
+ and include functionality for tracing and error reporting.
+ It will also fit into an OTP supervision tree. Refer to
+ <seealso marker="doc/design_principles:statem">
+ OTP Design Principles
+ </seealso>
+ for more information.
+ </p>
+ <p>
+ A <c>gen_statem</c> assumes all specific parts to be located in a
+ callback module exporting a pre-defined set of functions.
+ The relationship between the behaviour functions and the callback
+ functions can be illustrated as follows:</p>
+ <pre>
+gen_statem module Callback module
+----------------- ---------------
+gen_statem:start
+gen_statem:start_link -----> Module:init/1
+
+gen_statem:stop -----> Module:terminate/3
+
+gen_statem:call
+gen_statem:cast
+erlang:send
+erlang:'!' -----> Module:StateName/3
+ Module:handle_event/4
+
+- -----> Module:terminate/3
+
+- -----> Module:code_change/4</pre>
+ <p>
+ Events are of different
+ <seealso marker="#type-event_type">types</seealso>
+ so the callback functions can know the origin of an event
+ and how to respond.
+ </p>
+ <p>
+ If a callback function fails or returns a bad value,
+ the <c>gen_statem</c> will terminate. An exception of class
+ <seealso marker="erts:erlang#throw/1"><c>throw</c></seealso>,
+ however, is not regarded as an error but as a valid return.
+ </p>
+ <marker id="state_function" />
+ <p>
+ The "<em>state function</em>" for a specific
+ <seealso marker="#type-state">state</seealso>
+ in a <c>gen_statem</c> is the callback function that is called
+ for all events in this state, and is selected depending on which
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
+ that the implementation specifies when the the server starts.
+ </p>
+ <p>
+ When the
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
+ is <c>state_functions</c>, the state has to be an atom and
+ is used as the state function name. See
+ <seealso marker="#Module:StateName/3">
+ <c>Module:StateName/3</c>
+ </seealso>.
+ This gathers all code for a specific state
+ in one function and hence dispatches on state first.
+ Note that in this mode the fact that there is
+ a mandatory callback function
+ <seealso marker="#Module:terminate/3">
+ <c>Module:terminate/3</c>
+ </seealso> makes the state name <c>terminate</c> unusable.
+ </p>
+ <p>
+ When the
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
+ is <c>handle_event_function</c> the state can be any term
+ and the state function name is
+ <seealso marker="#Module:handle_event/4">
+ <c>Module:handle_event/4</c>
+ </seealso>.
+ This makes it easy to dispatch on state or on event as you desire.
+ Be careful about which events you handle in which
+ states so you do not accidentally postpone one event
+ forever creating an infinite busy loop.
+ </p>
+ <p>
+ The <c>gen_statem</c> enqueues incoming events in order of arrival
+ and presents these to the
+ <seealso marker="#state_function">state function</seealso>
+ in that order. The state function can postpone an event
+ so it is not retried in the current state.
+ After a state change the queue restarts with the postponed events.
+ </p>
+ <p>
+ The <c>gen_statem</c> event queue model is sufficient
+ to emulate the normal process message queue with selective receive.
+ Postponing an event corresponds to not matching it
+ in a receive statement and changing states corresponds
+ to entering a new receive statement.
+ </p>
+ <p>
+ The <seealso marker="#state_function">state function</seealso>
+ can insert events using the
+ <seealso marker="#type-action">
+ <c>action()</c> <c>next_event</c>
+ </seealso>
+ and such an event is inserted as the next to present
+ to the state function. That is: as if it is
+ the oldest incoming event. There is a dedicated
+ <seealso marker="#type-event_type">
+ <c>event_type()</c>
+ </seealso>
+ <c>internal</c> that can be used for such events making them impossible
+ to mistake for external events.
+ </p>
+ <p>
+ Inserting an event replaces the trick of calling your own
+ state handling functions that you often would have to
+ resort to in for example <seealso marker="gen_fsm"><c>gen_fsm</c></seealso>
+ to force processing an inserted event before others.
+ A warning, though: if you in <c>gen_statem</c> for example
+ postpone an event in one state and then call some other state function of yours,
+ you have not changed states and hence the postponed event will not be retried,
+ which is logical but might be confusing.
+ </p>
+ <p>
+ See the type
+ <seealso marker="#type-transition_option">
+ <c>transition_option()</c>
+ </seealso>
+ for the details of a state transition.
+ </p>
+ <p>
+ A <c>gen_statem</c> handles system messages as documented in
+ <seealso marker="sys"><c>sys</c></seealso>.
+ The <c>sys</c>module can be used for debugging a <c>gen_statem</c>.
+ </p>
+ <p>
+ Note that a <c>gen_statem</c> does not trap exit signals
+ automatically, this must be explicitly initiated in
+ the callback module (by calling
+ <seealso marker="erts:erlang#process_flag/2">
+ <c>process_flag(trap_exit, true)</c></seealso>.
+ </p>
+ <p>
+ Unless otherwise stated, all functions in this module fail if
+ the specified <c>gen_statem</c> does not exist or
+ if bad arguments are given.
+ </p>
+ <p>
+ The <c>gen_statem</c> process can go into hibernation; see
+ <seealso marker="proc_lib#hibernate/3">
+ <c>proc_lib:hibernate/3</c>.
+ </seealso>
+ It is done when a
+ <seealso marker="#state_function">state function</seealso> or
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ specifies <c>hibernate</c> in the returned
+ <seealso marker="#type-action"><c>Actions</c></seealso>
+ list. This feature might be useful to reclaim process heap memory
+ while the server is expected to be idle for a long time.
+ However, use this feature with care
+ since hibernation can be too costly
+ to use after every event; see
+ <seealso marker="erts:erlang#hibernate/3">
+ <c>erlang:hibernate/3</c>.
+ </seealso>
+ </p>
+ </description>
+
+ <section>
+ <title>EXAMPLE</title>
+ <p>
+ This example shows a simple pushbutton model
+ for a toggling pushbutton implemented with
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
+ <c>state_functions</c>.
+ You can push the button and it replies if it went on or off,
+ and you can ask for a count of how many times it has been
+ pushed to on.
+ </p>
+ <p>This is the complete callback module file <c>pushbutton.erl</c>:</p>
+ <code type="erl">
+-module(pushbutton).
+-behaviour(gen_statem).
+
+-export([start/0,push/0,get_count/0,stop/0]).
+-export([terminate/3,code_change/4,init/1]).
+-export([on/3,off/3]).
+
+name() -> pushbutton_statem. % The registered server name
+callback_mode() -> state_functions.
+
+%% API. This example uses a registered name name()
+%% and does not link to the caller.
+start() ->
+ gen_statem:start({local,name()}, ?MODULE, [], []).
+push() ->
+ gen_statem:call(name(), push).
+get_count() ->
+ gen_statem:call(name(), get_count).
+stop() ->
+ gen_statem:stop(name()).
+
+%% Mandatory callback functions
+terminate(_Reason, _State, _Data) ->
+ void.
+code_change(_Vsn, State, Data, _Extra) ->
+ {callback_mode(),State,Data}.
+init([]) ->
+ %% Set the callback mode and initial state + data.
+ %% Data is used only as a counter.
+ State = off, Data = 0,
+ {callback_mode(),State,Data}.
+
+
+%%% State functions
+
+off({call,From}, push, Data) ->
+ %% Go to 'on', increment count and reply
+ %% that the resulting status is 'on'
+ {next_state,on,Data+1,[{reply,From,on}]};
+off(EventType, EventContent, Data) ->
+ handle_event(EventType, EventContent, Data).
+
+on({call,From}, push, Data) ->
+ %% Go to 'off' and reply that the resulting status is 'off'
+ {next_state,off,Data,[{reply,From,off}]};
+on(EventType, EventContent, Data) ->
+ handle_event(EventType, EventContent, Data).
+
+%% Handle events common to all states
+handle_event({call,From}, get_count, Data) ->
+ %% Reply with the current count
+ {keep_state,Data,[{reply,From,Data}]};
+handle_event(_, _, Data) ->
+ %% Ignore all other events
+ {keep_state,Data}.
+ </code>
+ <p>And this is a shell session when running it:</p>
+ <pre>
+1> pushbutton:start().
+{ok,&lt;0.36.0>}
+2> pushbutton:get_count().
+0
+3> pushbutton:push().
+on
+4> pushbutton:get_count().
+1
+5> pushbutton:push().
+off
+6> pushbutton:get_count().
+1
+7> pushbutton:stop().
+ok
+8> pushbutton:push().
+** exception exit: {noproc,{gen_statem,call,[pushbutton_statem,push,infinity]}}
+ in function gen:do_for_proc/2 (gen.erl, line 261)
+ in call from gen_statem:call/3 (gen_statem.erl, line 386)
+ </pre>
+
+ <p>
+ And just to compare styles here is the same example using
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
+ <c>state_functions</c>, or rather here is code to replace
+ from the <c>init/1</c> function of the <c>pushbutton.erl</c>
+ example file above:
+ </p>
+ <code type="erl">
+init([]) ->
+ %% Set the callback mode and initial state + data.
+ %% Data is used only as a counter.
+ State = off, Data = 0,
+ {handle_event_function,State,Data}.
+
+
+%%% Event handling
+
+handle_event({call,From}, push, off, Data) ->
+ %% Go to 'on', increment count and reply
+ %% that the resulting status is 'on'
+ {next_state,on,Data+1,[{reply,From,on}]};
+handle_event({call,From}, push, on, Data) ->
+ %% Go to 'off' and reply that the resulting status is 'off'
+ {next_state,off,Data,[{reply,From,off}]};
+%%
+%% Event handling common to all states
+handle_event({call,From}, get_count, State, Data) ->
+ %% Reply with the current count
+ {next_state,State,Data,[{reply,From,Data}]};
+handle_event(_, _, State, Data) ->
+ %% Ignore all other events
+ {next_state,State,Data}.
+ </code>
+ </section>
+
+ <datatypes>
+ <datatype>
+ <name name="server_name" />
+ <desc>
+ <p>
+ Name specification to use when starting
+ a <c>gen_statem</c> server. See
+ <seealso marker="#start_link/3">
+ <c>start_link/3</c>
+ </seealso>
+ and
+ <seealso marker="#type-server_ref">
+ <c>server_ref()</c>
+ </seealso> below.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="server_ref" />
+ <desc>
+ <p>
+ Server specification to use when addressing
+ a <c>gen_statem</c> server.
+ See <seealso marker="#call/2"><c>call/2</c></seealso> and
+ <seealso marker="#type-server_name">
+ <c>server_name()</c>
+ </seealso>
+ above.
+ </p>
+ <p>It can be:</p>
+ <taglist>
+ <tag><c>pid()</c><br />
+ <c>LocalName</c></tag>
+ <item>The <c>gen_statem</c> is locally registered.</item>
+ <tag><c>Name, Node</c></tag>
+ <item>
+ The <c>gen_statem</c> is locally registered
+ on another node.
+ </item>
+ <tag><c>GlobalName</c></tag>
+ <item>
+ The <c>gen_statem</c> is globally registered
+ in <seealso marker="kernel:global"><c>global</c></seealso>.
+ </item>
+ <tag><c>RegMod, ViaName</c></tag>
+ <item>
+ The <c>gen_statem</c> is registered through
+ an alternative process registry.
+ The registry callback module <c>RegMod</c>
+ should export the functions
+ <c>register_name/2</c>, <c>unregister_name/1</c>,
+ <c>whereis_name/1</c> and <c>send/2</c>,
+ which should behave like the corresponding functions
+ in <seealso marker="kernel:global"><c>global</c></seealso>.
+ Thus, <c>{via,global,GlobalName}</c> is the same as
+ <c>{global,GlobalName}</c>.
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="debug_opt" />
+ <desc>
+ <p>
+ Debug option that can be used when starting
+ a <c>gen_statem</c> server through for example
+ <seealso marker="#enter_loop/5"><c>enter_loop/5</c></seealso>.
+ </p>
+ <p>
+ For every entry in <c><anno>Dbgs</anno></c>
+ the corresponding function in
+ <seealso marker="sys"><c>sys</c></seealso> will be called.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="start_opt" />
+ <desc>
+ <p>
+ Options that can be used when starting
+ a <c>gen_statem</c> server through for example
+ <seealso marker="#start_link/3"><c>start_link/3</c></seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="start_ret" />
+ <desc>
+ <p>
+ Return value from the start functions for_example
+ <seealso marker="#start_link/3"><c>start_link/3</c></seealso>.
+ </p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="from" />
+ <desc>
+ <p>
+ Destination to use when replying through for example the
+ <seealso marker="#type-action">
+ <c>action()</c>
+ </seealso>
+ <c>{reply,From,Reply}</c>
+ to a process that has called the <c>gen_statem</c> server using
+ <seealso marker="#call/2"><c>call/2</c></seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="state" />
+ <desc>
+ <p>
+ After a state change (<c>NextState =/= State</c>)
+ all postponed events are retried.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="state_name" />
+ <desc>
+ <p>
+ If the
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
+ is <c>state_functions</c>,
+ the state has to be of this type.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="data" />
+ <desc>
+ <p>
+ A term in which the state machine implementation
+ should store any server data it needs. The difference between
+ this and the <seealso marker="#type-state"><c>state()</c></seealso>
+ itself is that a change in this data does not cause
+ postponed events to be retried. Hence if a change
+ in this data would change the set of events that
+ are handled than that data item should be made
+ a part of the state.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="event_type" />
+ <desc>
+ <p>
+ External events are of 3 different type:
+ <c>{call,<anno>From</anno>}</c>, <c>cast</c> or <c>info</c>.
+ <seealso marker="#call/2">Calls</seealso>
+ (synchronous) and
+ <seealso marker="#cast/2">casts</seealso>
+ originate from the corresponding API functions.
+ For calls the event contain whom to reply to.
+ Type <c>info</c> originates from regular process messages sent
+ to the <c>gen_statem</c>. It is also possible for the state machine
+ implementation to generate events of types
+ <c>timeout</c> and <c>internal</c> to itself.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="callback_mode" />
+ <desc>
+ <p>
+ The <em>callback mode</em> is selected when starting the
+ <c>gen_statem</c> using the return value from
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ or when calling
+ <seealso marker="#enter_loop/5"><c>enter_loop/5-7</c></seealso>,
+ and with the return value from
+ <seealso marker="#Module:code_change/4">
+ <c>Module:code_change/4</c>.
+ </seealso>
+ </p>
+ <taglist>
+ <tag><c>state_functions</c></tag>
+ <item>
+ The state has to be of type
+ <seealso marker="#type-state_name"><c>state_name()</c></seealso>
+ and one callback function per state that is
+ <seealso marker="#Module:StateName/3">
+ <c>Module:StateName/3</c>
+ </seealso>
+ is used.
+ </item>
+ <tag><c>handle_event_function</c></tag>
+ <item>
+ The state can be any term and the callback function
+ <seealso marker="#Module:handle_event/4">
+ <c>Module:handle_event/4</c>
+ </seealso>
+ is used for all states.
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="transition_option" />
+ <desc>
+ <p>
+ Transition options may be set by
+ <seealso marker="#type-action">actions</seealso>
+ and they modify some details below in how
+ the state transition is done:
+ </p>
+ <list type="ordered">
+ <item>
+ All
+ <seealso marker="#type-action">actions</seealso>
+ are processed in order of appearance.
+ </item>
+ <item>
+ If
+ <seealso marker="#type-postpone">
+ <c>postpone()</c>
+ </seealso>
+ is <c>true</c>
+ the current event is postponed.
+ </item>
+ <item>
+ If the state changes the queue of incoming events
+ is reset to start with the oldest postponed.
+ </item>
+ <item>
+ All events stored with
+ <seealso marker="#type-action">
+ <c>action()</c>
+ </seealso>
+ <c>next_event</c>
+ are inserted in the queue to be processed before
+ all other events.
+ </item>
+ <item>
+ If an
+ <seealso marker="#type-event_timeout">
+ <c>event_timeout()</c>
+ </seealso>
+ is set through
+ <seealso marker="#type-action">
+ <c>action()</c>
+ </seealso>
+ <c>timeout</c>
+ an event timer may be started or a timeout zero event
+ may be enqueued.
+ </item>
+ <item>
+ The (possibly new)
+ <seealso marker="#state_function">state function</seealso>
+ is called with the oldest enqueued event if there is any,
+ otherwise the <c>gen_statem</c> goes into <c>receive</c>
+ or hibernation
+ (if
+ <seealso marker="#type-hibernate">
+ <c>hibernate()</c>
+ </seealso>
+ is <c>true</c>)
+ to wait for the next message. In hibernation the next
+ non-system event awakens the <c>gen_statem</c>, or rather
+ the next incoming message awakens the <c>gen_statem</c>
+ but if it is a system event
+ it goes right back into hibernation.
+ </item>
+ </list>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="postpone" />
+ <desc>
+ <p>
+ If <c>true</c> postpone the current event and retry
+ it when the state changes
+ (<c>NextState =/= State</c>).
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="hibernate" />
+ <desc>
+ <p>
+ If <c>true</c> hibernate the <c>gen_statem</c>
+ by calling
+ <seealso marker="proc_lib#hibernate/3">
+ <c>proc_lib:hibernate/3</c>
+ </seealso>
+ before going into <c>receive</c>
+ to wait for a new external event.
+ If there are enqueued events,
+ to prevent receiving any new event; a
+ <seealso marker="erts:erlang#garbage_collect/0">
+ <c>garbage_collect/0</c>
+ </seealso> is done instead to simulate
+ that the <c>gen_statem</c> entered hibernation
+ and immediately got awakened by the oldest enqueued event.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="event_timeout" />
+ <desc>
+ <p>
+ Generate an event of
+ <seealso marker="#type-event_type"><c>event_type()</c></seealso>
+ <c>timeout</c>
+ after this time (in milliseconds) unless some other
+ event arrives in which case this timeout is cancelled.
+ Note that a retried or inserted event
+ counts just like a new in this respect.
+ </p>
+ <p>
+ If the value is <c>infinity</c> no timer is started since
+ it will never trigger anyway.
+ </p>
+ <p>
+ If the value is <c>0</c> the timeout event is immediately enqueued
+ unless there already are enqueued events since then the
+ timeout is immediately cancelled.
+ This is a feature ensuring that a timeout <c>0</c> event
+ will be processed before any not yet received external event.
+ </p>
+ <p>
+ Note that it is not possible nor needed to cancel this timeout
+ since it is cancelled automatically by any other event.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="action" />
+ <desc>
+ <p>
+ These state transition actions may be invoked by
+ returning them from the
+ <seealso marker="#state_function">state function</seealso>,
+ from <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ or by giving them to
+ <seealso marker="#enter_loop/6"><c>enter_loop/6,7</c></seealso>.
+ </p>
+ <p>
+ Actions are executed in the containing list order.
+ </p>
+ <p>
+ Actions that set
+ <seealso marker="#type-transition_option">
+ transition options
+ </seealso>
+ overrides any previous of the same type,
+ so the last in the containing list wins.
+ For example the last
+ <seealso marker="#type-event_timeout">
+ <c>event_timeout()</c>
+ </seealso>
+ overrides any other <c>event_timeout()</c> in the list.
+ </p>
+ <taglist>
+ <tag><c>postpone</c></tag>
+ <item>
+ Set the
+ <seealso marker="#type-transition_option">
+ <c>transition_option()</c>
+ </seealso>
+ <seealso marker="#type-postpone">
+ <c>postpone()</c>
+ </seealso>
+ for this state transition.
+ This action is ignored when returned from
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ or given to
+ <seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>
+ since there is no event to postpone in those cases.
+ </item>
+ <tag><c>hibernate</c></tag>
+ <item>
+ Set the
+ <seealso marker="#type-transition_option">
+ <c>transition_option()</c>
+ </seealso>
+ <seealso marker="#type-hibernate">
+ <c>hibernate()</c>
+ </seealso>
+ for this state transition.
+ </item>
+ <tag><c>Timeout</c></tag>
+ <item>
+ Short for <c>{timeout,Timeout,Timeout}</c> that is
+ the timeout message is the timeout time.
+ This form exists to make the
+ <seealso marker="#state_function">state function</seealso>
+ return value <c>{next_state,NextState,NewData,Timeout}</c>
+ allowed like for
+ <seealso marker="gen_fsm#Module:StateName/2">
+ <c>gen_fsm Module:StateName/2</c>.
+ </seealso>
+ </item>
+ <tag><c>timeout</c></tag>
+ <item>
+ Set the
+ <seealso marker="#type-transition_option">
+ <c>transition_option()</c>
+ </seealso>
+ <seealso marker="#type-event_timeout">
+ <c>event_timeout()</c>
+ </seealso>
+ to <c><anno>Time</anno></c> with <c><anno>EventContent</anno></c>.
+ </item>
+ <tag><c>reply_action()</c></tag>
+ <item>Reply to a caller.</item>
+ <tag><c>next_event</c></tag>
+ <item>
+ Store the given <c><anno>EventType</anno></c>
+ and <c><anno>EventContent</anno></c> for insertion after all
+ actions have been executed.
+ </item>
+ <item>
+ <p>
+ The stored events are inserted in the queue as the next to process
+ before any already queued events. The order of these stored events
+ is preserved so the first <c>next_event</c> in the containing list
+ will become the first to process.
+ </p>
+ </item>
+ <item>
+ <p>
+ An event of type
+ <seealso marker="#type-event_type">
+ <c>internal</c>
+ </seealso>
+ should be used when you want to reliably distinguish
+ an event inserted this way from any external event.
+ </p>
+ </item>
+ </taglist>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="reply_action" />
+ <desc>
+ <p>
+ Reply to a caller waiting for a reply in
+ <seealso marker="#call/2"><c>call/2</c></seealso>.
+ <c><anno>From</anno></c> must be the term from the
+ <seealso marker="#type-event_type">
+ <c>{call,<anno>From</anno>}</c>
+ </seealso>
+ argument to the
+ <seealso marker="#state_function">state function</seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="state_function_result" />
+ <desc>
+ <taglist>
+ <tag><c>next_state</c></tag>
+ <item>
+ The <c>gen_statem</c> will do a state transition to
+ <c><anno>NextStateName</anno></c>
+ (which may be the same as the current state),
+ set <c><anno>NewData</anno></c>
+ and execute all <c><anno>Actions</anno></c>
+ </item>
+ </taglist>
+ <p>
+ All these terms are tuples or atoms and this property
+ will hold in any future version of <c>gen_statem</c>,
+ just in case you need such a promise.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="handle_event_result" />
+ <desc>
+ <taglist>
+ <tag><c>next_state</c></tag>
+ <item>
+ The <c>gen_statem</c> will do a state transition to
+ <c><anno>NextState</anno></c>
+ (which may be the same as the current state),
+ set <c><anno>NewData</anno></c>
+ and execute all <c><anno>Actions</anno></c>
+ </item>
+ </taglist>
+ <p>
+ All these terms are tuples or atoms and this property
+ will hold in any future version of <c>gen_statem</c>,
+ just in case you need such a promise.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="common_state_callback_result" />
+ <desc>
+ <taglist>
+ <tag><c>stop</c></tag>
+ <item>
+ Terminate the <c>gen_statem</c> by calling
+ <seealso marker="#Module:terminate/3">
+ <c>Module:terminate/3</c>
+ </seealso>
+ with <c>Reason</c> and
+ <c><anno>NewData</anno></c>, if given.
+ </item>
+ <tag><c>stop_and_reply</c></tag>
+ <item>
+ Send all <c><anno>Replies</anno></c>
+ then terminate the <c>gen_statem</c> by calling
+ <seealso marker="#Module:terminate/3">
+ <c>Module:terminate/3</c>
+ </seealso>
+ with <c>Reason</c> and
+ <c><anno>NewData</anno></c>, if given.
+ </item>
+ <tag><c>keep_state</c></tag>
+ <item>
+ The <c>gen_statem</c> will keep the current state, or
+ do a state transition to the current state if you like,
+ set <c><anno>NewData</anno></c>
+ and execute all <c><anno>Actions</anno></c>.
+ This is the same as
+ <c>{next_state,CurrentState,<anno>NewData</anno>,<anno>Actions</anno>}</c>.
+ </item>
+ <tag><c>keep_state_and_data</c></tag>
+ <item>
+ The <c>gen_statem</c> will keep the current state or
+ do a state transition to the current state if you like,
+ keep the current server data,
+ and execute all <c><anno>Actions</anno></c>.
+ This is the same as
+ <c>{next_state,CurrentState,CurrentData,<anno>Actions</anno>}</c>.
+ </item>
+ </taglist>
+ <p>
+ All these terms are tuples or atoms and this property
+ will hold in any future version of <c>gen_statem</c>,
+ just in case you need such a promise.
+ </p>
+ </desc>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+
+ <func>
+ <name name="start_link" arity="3" />
+ <name name="start_link" arity="4" />
+ <fsummary>Create a linked <c>gen_statem</c> process</fsummary>
+ <desc>
+ <p>
+ Creates a <c>gen_statem</c> process according
+ to OTP design principles
+ (using
+ <seealso marker="proc_lib"><c>proc_lib</c></seealso>
+ primitives)
+ that is linked to the calling process.
+ This is essential when the <c>gen_statem</c> shall be part of
+ a supervision tree so it gets linked to its supervisor.
+ </p>
+ <p>
+ The <c>gen_statem</c> process calls
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ to initialize the server. To ensure a synchronized start-up
+ procedure, <c>start_link/3,4</c> does not return until
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ has returned.
+ </p>
+ <p>
+ <c><anno>ServerName</anno></c> specifies the
+ <seealso marker="#type-server_name">
+ <c>server_name()</c>
+ </seealso>
+ to register for the <c>gen_statem</c>.
+ If the <c>gen_statem</c> is started with <c>start_link/3</c>
+ no <c><anno>ServerName</anno></c> is provided and
+ the <c>gen_statem</c> is not registered.
+ </p>
+ <p><c><anno>Module</anno></c> is the name of the callback module.</p>
+ <p>
+ <c><anno>Args</anno></c> is an arbitrary term which is passed as
+ the argument to
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>.
+ </p>
+ <p>
+ If the option <c>{timeout,Time}</c> is present in
+ <c><anno>Opts</anno></c>, the <c>gen_statem</c>
+ is allowed to spend <c>Time</c> milliseconds initializing
+ or it will be terminated and the start function will return
+ <seealso marker="#type-start_ret"><c>{error,timeout}</c></seealso>.
+ </p>
+ <p>
+ If the option
+ <seealso marker="#type-debug_opt"><c>{debug,Dbgs}</c></seealso>
+ is present in <c><anno>Opts</anno></c>, debugging through
+ <seealso marker="sys"><c>sys</c></seealso> is activated.
+ </p>
+ <p>
+ If the option <c>{spawn_opt,SpawnOpts}</c> is present in
+ <c><anno>Opts</anno></c>, <c>SpawnOpts</c> will be passed
+ as option list to
+ <seealso marker="erts:erlang#spawn_opt/2"><c>spawn_opt/2</c></seealso>
+ which is used to spawn the <c>gen_statem</c> process.
+ </p>
+ <note>
+ <p>
+ Using the spawn option <c>monitor</c> is currently not
+ allowed, but will cause this function to fail with reason
+ <c>badarg</c>.
+ </p>
+ </note>
+ <p>
+ If the <c>gen_statem</c> is successfully created
+ and initialized this function returns
+ <seealso marker="#type-start_ret">
+ <c>{ok,Pid}</c>,
+ </seealso>
+ where <c>Pid</c> is the <c>pid()</c>
+ of the <c>gen_statem</c>.
+ If there already exists a process with the specified
+ <c><anno>ServerName</anno></c> this function returns
+ <seealso marker="#type-start_ret"><c>{error,{already_started,Pid}}</c></seealso>,
+ where <c>Pid</c> is the <c>pid()</c> of that process.
+ </p>
+ <p>
+ If <c>Module:init/1</c> fails with <c>Reason</c>,
+ this function returns
+ <seealso marker="#type-start_ret"><c>{error,Reason}</c></seealso>.
+ If <c>Module:init/1</c> returns
+ <seealso marker="#type-start_ret">
+ <c>{stop,Reason}</c>
+ </seealso>
+ or
+ <seealso marker="#type-start_ret"><c>ignore</c></seealso>,
+ the process is terminated and this function
+ returns
+ <seealso marker="#type-start_ret">
+ <c>{error,Reason}</c>
+ </seealso>
+ or
+ <seealso marker="#type-start_ret"><c>ignore</c></seealso>,
+ respectively.
+ </p>
+ </desc>
+ </func>
+
+
+ <func>
+ <name name="start" arity="3" />
+ <name name="start" arity="4" />
+ <fsummary>Create a stand-alone <c>gen_statem</c> process</fsummary>
+ <desc>
+ <p>
+ Creates a stand-alone <c>gen_statem</c> process according to
+ OTP design principles (using
+ <seealso marker="proc_lib"><c>proc_lib</c></seealso>
+ primitives).
+ Since it does not get linked to the calling process
+ this start function can not be used by a supervisor
+ to start a child.
+ </p>
+ <p>
+ See <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>
+ for a description of arguments and return values.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="stop" arity="1" />
+ <fsummary>Synchronously stop a generic server</fsummary>
+ <desc>
+ <p>
+ The same as
+ <seealso marker="#stop/3">
+ <c>stop(<anno>ServerRef</anno>, normal, infinity)</c>.
+ </seealso>
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="stop" arity="3" />
+ <fsummary>Synchronously stop a generic server</fsummary>
+ <desc>
+ <p>
+ Orders the <c>gen_statem</c>
+ <seealso marker="#type-server_ref">
+ <c><anno>ServerRef</anno></c>
+ </seealso>
+ to exit with the given <c><anno>Reason</anno></c>
+ and waits for it to terminate.
+ The <c>gen_statem</c> will call
+ <seealso marker="#Module:terminate/3">
+ <c>Module:terminate/3</c>
+ </seealso>
+ before exiting.
+ </p>
+ <p>
+ This function returns <c>ok</c> if the server terminates
+ with the expected reason. Any other reason than <c>normal</c>,
+ <c>shutdown</c>, or <c>{shutdown,Term}</c> will cause an
+ error report to be issued through
+ <seealso marker="kernel:error_logger#format/2">
+ <c>error_logger:format/2</c>.
+ </seealso>
+ The default <c><anno>Reason</anno></c> is <c>normal</c>.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> is an integer greater than zero
+ which specifies how many milliseconds to wait for the server to
+ terminate, or the atom <c>infinity</c> to wait indefinitely.
+ The default value is <c>infinity</c>.
+ If the server has not terminated within the specified time,
+ a <c>timeout</c> exception is raised.
+ </p>
+ <p>
+ If the process does not exist, a <c>noproc</c> exception
+ is raised.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="call" arity="2" />
+ <name name="call" arity="3" />
+ <fsummary>Make a synchronous call to a <c>gen_statem</c></fsummary>
+ <desc>
+ <p>
+ Makes a synchronous call to the <c>gen_statem</c>
+ <seealso marker="#type-server_ref">
+ <c><anno>ServerRef</anno></c>
+ </seealso>
+ by sending a request
+ and waiting until its reply arrives.
+ The <c>gen_statem</c> will call the
+ <seealso marker="#state_function">state function</seealso> with
+ <seealso marker="#type-event_type"><c>event_type()</c></seealso>
+ <c>{call,From}</c> and event content
+ <c><anno>Request</anno></c>.
+ </p>
+ <p>
+ A <c><anno>Reply</anno></c> is generated when a
+ <seealso marker="#state_function">state function</seealso>
+ returns with
+ <c>{reply,From,<anno>Reply</anno>}</c> as one
+ <seealso marker="#type-action"><c>action()</c></seealso>,
+ and that <c><anno>Reply</anno></c> becomes the return value
+ of this function.
+ </p>
+ <p>
+ <c><anno>Timeout</anno></c> is an integer greater than zero
+ which specifies how many milliseconds to wait for a reply,
+ or the atom <c>infinity</c> to wait indefinitely,
+ which is the default. If no reply is received within
+ the specified time, the function call fails.
+ </p>
+ <note>
+ <p>
+ To avoid getting a late reply in the caller's
+ inbox this function spawns a proxy process that
+ does the call. A late reply gets delivered to the
+ dead proxy process hence gets discarded. This is
+ less efficient than using
+ <c><anno>Timeout</anno> =:= infinity</c>.
+ </p>
+ </note>
+ <p>
+ The call may fail for example if the <c>gen_statem</c> dies
+ before or during this function call.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="cast" arity="2" />
+ <fsummary>Send an asynchronous event to a <c>gen_statem</c></fsummary>
+ <desc>
+ <p>
+ Sends an asynchronous event to the <c>gen_statem</c>
+ <seealso marker="#type-server_ref">
+ <c><anno>ServerRef</anno></c>
+ </seealso>
+ and returns <c>ok</c> immediately,
+ ignoring if the destination node or <c>gen_statem</c>
+ does not exist.
+ The <c>gen_statem</c> will call the
+ <seealso marker="#state_function">state function</seealso> with
+ <seealso marker="#type-event_type"><c>event_type()</c></seealso>
+ <c>cast</c> and event content
+ <c><anno>Msg</anno></c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="reply" arity="1" />
+ <name name="reply" arity="2" />
+ <fsummary>Reply to a caller</fsummary>
+ <desc>
+ <p>
+ This function can be used by a <c>gen_statem</c>
+ to explicitly send a reply to a process that waits in
+ <seealso marker="#call/2"><c>call/2</c></seealso>
+ when the reply cannot be defined in
+ the return value of a
+ <seealso marker="#state_function">state function</seealso>.
+ </p>
+ <p>
+ <c><anno>From</anno></c> must be the term from the
+ <seealso marker="#type-event_type">
+ <c>{call,<anno>From</anno>}</c>
+ </seealso>
+ argument to the
+ <seealso marker="#state_function">state function</seealso>.
+ <c><anno>From</anno></c> and <c><anno>Reply</anno></c>
+ can also be specified using a
+ <seealso marker="#type-reply_action">
+ <c>reply_action()</c>
+ </seealso>
+ and multiple replies with a list of them.
+ </p>
+ <note>
+ <p>
+ A reply sent with this function will not be visible
+ in <seealso marker="sys"><c>sys</c></seealso> debug output.
+ </p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="enter_loop" arity="5" />
+ <fsummary>Enter the <c>gen_statem</c> receive loop</fsummary>
+ <desc>
+ <p>
+ The same as
+ <seealso marker="#enter_loop/7"><c>enter_loop/7</c></seealso>
+ except that no
+ <seealso marker="#type-server_name">
+ <c>server_name()</c>
+ </seealso>
+ must have been registered.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="enter_loop" arity="6" />
+ <fsummary>Enter the <c>gen_statem</c> receive loop</fsummary>
+ <desc>
+ <p>
+ If <c><anno>Server_or_Actions</anno></c> is a <c>list()</c>
+ the same as
+ <seealso marker="#enter_loop/7"><c>enter_loop/7</c></seealso>
+ except that no
+ <seealso marker="#type-server_name">
+ <c>server_name()</c>
+ </seealso>
+ must have been registered and
+ <c>Actions = <anno>Server_or_Actions</anno></c>.
+ </p>
+ <p>
+ Otherwise the same as
+ <seealso marker="#enter_loop/7"><c>enter_loop/7</c></seealso>
+ with
+ <c>Server = <anno>Server_or_Actions</anno></c> and
+ <c>Actions = []</c>.
+ </p>
+ </desc>
+ </func>
+ <func>
+ <name name="enter_loop" arity="7" />
+ <fsummary>Enter the <c>gen_statem</c> receive loop</fsummary>
+ <desc>
+ <p>
+ Makes an the calling process become a <c>gen_statem</c>.
+ Does not return, instead the calling process will enter
+ the <c>gen_statem</c> receive loop and become
+ a <c>gen_statem</c> server.
+ The process <em>must</em> have been started
+ using one of the start functions in
+ <seealso marker="proc_lib"><c>proc_lib</c></seealso>.
+ The user is responsible for any initialization of the process,
+ including registering a name for it.
+ </p>
+ <p>
+ This function is useful when a more complex initialization
+ procedure is needed than
+ the <c>gen_statem</c> behaviour provides.
+ </p>
+ <p>
+ <c><anno>Module</anno></c>, <c><anno>Opts</anno></c> and
+ <c><anno>Server</anno></c> have the same meanings
+ as when calling
+ <seealso marker="#start_link/3">
+ <c>gen_statem:start[_link]/3,4</c>.
+ </seealso>
+ However, the
+ <seealso marker="#type-server_name">
+ <c>server_name()</c>
+ </seealso>
+ name must have been registered accordingly
+ <em>before</em> this function is called.</p>
+ <p>
+ <c><anno>CallbackMode</anno></c>, <c><anno>State</anno></c>,
+ <c><anno>Data</anno></c> and <c><anno>Actions</anno></c>
+ have the same meanings as in the return value of
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>.
+ Also, the callback module <c><anno>Module</anno></c>
+ does not need to export an <c>init/1</c> function.
+ </p>
+ <p>
+ Failure: If the calling process was not started by a
+ <seealso marker="proc_lib"><c>proc_lib</c></seealso>
+ start function, or if it is not registered
+ according to
+ <seealso marker="#type-server_name"><c>server_name()</c></seealso>.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+
+
+ <section>
+ <title>CALLBACK FUNCTIONS</title>
+ <p>
+ The following functions should be exported from a
+ <c>gen_statem</c> callback module.
+ </p>
+ </section>
+ <funcs>
+
+ <func>
+ <name>Module:init(Args) -> Result</name>
+ <fsummary>Initialize process and internal state</fsummary>
+ <type>
+ <v>Args = term()</v>
+ <v>Result = {CallbackMode,State,Data}</v>
+ <v>&nbsp;| {CallbackMode,State,Data,Actions}</v>
+ <v>&nbsp;| {stop,Reason} | ignore</v>
+ <v>
+ CallbackMode =
+ <seealso marker="#type-callback_mode">callback_mode()</seealso>
+ </v>
+ <v>State = <seealso marker="#type-state">state()</seealso></v>
+ <v>
+ Data = <seealso marker="#type-data">data()</seealso>
+ </v>
+ <v>
+ Actions =
+ [<seealso marker="#type-action">action()</seealso>] |
+ <seealso marker="#type-action">action()</seealso>
+ </v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <marker id="Module:init-1" />
+ <p>
+ Whenever a <c>gen_statem</c> is started using
+ <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>
+ or
+ <seealso marker="#start/3"><c>start/3,4</c></seealso>,
+ this function is called by the new process to initialize
+ the implementation state and server data.
+ </p>
+ <p>
+ <c>Args</c> is the <c>Args</c> argument provided to the start
+ function.
+ </p>
+ <p>
+ If the initialization is successful, the function should
+ return <c>{CallbackMode,State,Data}</c> or
+ <c>{CallbackMode,State,Data,Actions}</c>.
+ <c>CallbackMode</c> selects the
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>.
+ of the <c>gen_statem</c>.
+ <c>State</c> is the initial
+ <seealso marker="#type-state"><c>state()</c></seealso>
+ and <c>Data</c> the initial server
+ <seealso marker="#type-data"><c>data()</c></seealso>.
+ </p>
+ <p>
+ The <seealso marker="#type-action"><c>Actions</c></seealso>
+ are executed when entering the first
+ <seealso marker="#type-state">state</seealso> just as for a
+ <seealso marker="#state_function">state function</seealso>.
+ </p>
+ <p>
+ If something goes wrong during the initialization
+ the function should return <c>{stop,Reason}</c>
+ or <c>ignore</c>. See
+ <seealso marker="#start_link/3"><c>start_link/3,4</c></seealso>.
+ </p>
+ <p>
+ This function may use
+ <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>
+ to return <c>Result</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:StateName(EventType, EventContent, Data) ->
+ StateFunctionResult
+ </name>
+ <name>Module:handle_event(EventType, EventContent,
+ State, Data) -> HandleEventResult
+ </name>
+ <fsummary>Handle an event</fsummary>
+ <type>
+ <v>
+ EventType =
+ <seealso marker="#type-event_type">event_type()</seealso>
+ </v>
+ <v>EventContent = term()</v>
+ <v>
+ State =
+ <seealso marker="#type-state">state()</seealso>
+ </v>
+ <v>
+ Data = NewData =
+ <seealso marker="#type-data">data()</seealso>
+ </v>
+ <v>
+ StateFunctionResult =
+ <seealso marker="#type-state_function_result">
+ state_function_result()
+ </seealso>
+ </v>
+ <v>
+ HandleEventResult =
+ <seealso marker="#type-handle_event_result">
+ handle_event_result()
+ </seealso>
+ </v>
+ </type>
+ <desc>
+ <p>
+ Whenever a <c>gen_statem</c> receives an event from
+ <seealso marker="#call/2"><c>call/2</c></seealso>,
+ <seealso marker="#cast/2"><c>cast/2</c></seealso> or
+ as a normal process message one of these functions is called. If
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
+ is <c>state_functions</c> then <c>Module:StateName/3</c> is called,
+ and if it is <c>handle_event_function</c>
+ then <c>Module:handle_event/4</c> is called.
+ </p>
+ <p>
+ If <c>EventType</c> is
+ <seealso marker="#type-event_type"><c>{call,From}</c></seealso>
+ the caller is waiting for a reply. The reply can be sent
+ from this or from any other
+ <seealso marker="#state_function">state function</seealso>
+ by returning with <c>{reply,From,Reply}</c> in
+ <seealso marker="#type-action"><c>Actions</c></seealso>, in
+ <seealso marker="#type-reply_action"><c>Replies</c></seealso>
+ or by calling
+ <seealso marker="#reply/2"><c>reply(From, Reply)</c></seealso>.
+ </p>
+ <p>
+ If this function returns with a next state that
+ does not match equal (<c>=/=</c>) to the current state
+ all postponed events will be retried in the next state.
+ </p>
+ <p>
+ The only difference between <c>StateFunctionResult</c> and
+ <c>HandleEventResult</c> is that for <c>StateFunctionResult</c>
+ the next state has to be an atom but for <c>HandleEventResult</c>
+ there is no restriction on the next state.
+ </p>
+ <p>
+ See <seealso marker="#type-action"><c>action()</c></seealso>
+ for options that can be set and actions that can be done
+ by <c>gen_statem</c> after returning from this function.
+ </p>
+ <p>
+ These functions may use
+ <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>,
+ to return the result.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:terminate(Reason, State, Data) -> Ignored</name>
+ <fsummary>Clean up before termination</fsummary>
+ <type>
+ <v>Reason = normal | shutdown | {shutdown,term()} | term()</v>
+ <v>State = <seealso marker="#type-state">state()</seealso></v>
+ <v>Data = <seealso marker="#type-data">data()</seealso></v>
+ <v>Ignored = term()</v>
+ </type>
+ <desc>
+ <p>
+ This function is called by a <c>gen_statem</c>
+ when it is about to terminate. It should be the opposite of
+ <seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
+ and do any necessary cleaning up. When it returns,
+ the <c>gen_statem</c> terminates with <c>Reason</c>. The return
+ value is ignored.</p>
+ <p>
+ <c>Reason</c> is a term denoting the stop reason and
+ <seealso marker="#type-state"><c>State</c></seealso>
+ is the internal state of the <c>gen_statem</c>.
+ </p>
+ <p>
+ <c>Reason</c> depends on why the <c>gen_statem</c>
+ is terminating.
+ If it is because another callback function has returned a
+ stop tuple <c>{stop,Reason}</c> in
+ <seealso marker="#type-action"><c>Actions</c></seealso>,
+ <c>Reason</c> will have the value specified in that tuple.
+ If it is due to a failure, <c>Reason</c> is the error reason.
+ </p>
+ <p>
+ If the <c>gen_statem</c> is part of a supervision tree and is
+ ordered by its supervisor to terminate, this function will be
+ called with <c>Reason = shutdown</c> if the following
+ conditions apply:</p>
+ <list type="bulleted">
+ <item>
+ the <c>gen_statem</c> has been set
+ to trap exit signals, and
+ </item>
+ <item>
+ the shutdown strategy as defined in the supervisor's
+ child specification is an integer timeout value, not
+ <c>brutal_kill</c>.
+ </item>
+ </list>
+ <p>
+ Even if the <c>gen_statem</c> is <em>not</em>
+ part of a supervision tree, this function will be called
+ if it receives an <c>'EXIT'</c> message from its parent.
+ <c>Reason</c> will be the same as
+ in the <c>'EXIT'</c> message.
+ </p>
+ <p>
+ Otherwise, the <c>gen_statem</c> will be immediately terminated.
+ </p>
+ <p>
+ Note that for any other reason than <c>normal</c>,
+ <c>shutdown</c>, or <c>{shutdown,Term}</c>
+ the <c>gen_statem</c> is assumed to terminate due to an error
+ and an error report is issued using
+ <seealso marker="kernel:error_logger#format/2">
+ <c>error_logger:format/2</c>.
+ </seealso>
+ </p>
+ <p>
+ This function may use
+ <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>
+ to return <c>Ignored</c>, which is ignored anyway.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:code_change(OldVsn, OldState, OldData, Extra) ->
+ Result
+ </name>
+ <fsummary>Update the internal state during upgrade/downgrade</fsummary>
+ <type>
+ <v>OldVsn = Vsn | {down,Vsn}</v>
+ <v>&nbsp;&nbsp;Vsn = term()</v>
+ <v>OldState = NewState = term()</v>
+ <v>Extra = term()</v>
+ <v>Result = {NewCallbackMode,NewState,NewData} | Reason</v>
+ <v>
+ NewCallbackMode =
+ <seealso marker="#type-callback_mode">callback_mode()</seealso>
+ </v>
+ <v>
+ OldState = NewState =
+ <seealso marker="#type-state">state()</seealso>
+ </v>
+ <v>
+ OldData = NewData =
+ <seealso marker="#type-data">data()</seealso>
+ </v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>
+ This function is called by a <c>gen_statem</c> when it should
+ update its internal state during a release upgrade/downgrade,
+ that is when the instruction <c>{update,Module,Change,...}</c>
+ where <c>Change={advanced,Extra}</c> is given in the
+ <seealso marker="sasl:appup"><c>appup</c></seealso>
+ file. See
+ <seealso marker="doc/design_principles:release_handling#instr">
+ OTP Design Principles
+ </seealso>
+ for more information.
+ </p>
+ <p>
+ In the case of an upgrade, <c>OldVsn</c> is <c>Vsn</c>, and
+ in the case of a downgrade, <c>OldVsn</c> is
+ <c>{down,Vsn}</c>. <c>Vsn</c> is defined by the <c>vsn</c>
+ attribute(s) of the old version of the callback module
+ <c>Module</c>. If no such attribute is defined, the version
+ is the checksum of the BEAM file.
+ </p>
+ <note>
+ <p>
+ If you would dare to change
+ <seealso marker="#type-callback_mode">
+ <em>callback mode</em>
+ </seealso>
+ during release upgrade/downgrade, the upgrade is no problem
+ since the new code surely knows what <em>callback mode</em>
+ it needs, but for a downgrade this function will have to
+ know from the <c>Extra</c> argument that comes from the
+ <seealso marker="sasl:appup"><c>appup</c></seealso>
+ file what <em>callback mode</em> the old code did use.
+ It may also be possible to figure this out
+ from the <c>{down,Vsn}</c> argument since <c>Vsn</c>
+ in effect defines the old callback module version.
+ </p>
+ </note>
+ <p>
+ <c>OldState</c> and <c>OldData</c> is the internal state
+ of the <c>gen_statem</c>.
+ </p>
+ <p>
+ <c>Extra</c> is passed as-is from the <c>{advanced,Extra}</c>
+ part of the update instruction.
+ </p>
+ <p>
+ If successful, the function shall return the updated
+ internal state in an
+ <c>{NewCallbackMode,NewState,NewData}</c> tuple.
+ </p>
+ <p>
+ If the function returns <c>Reason</c>, the ongoing
+ upgrade will fail and roll back to the old release.</p>
+ <p>
+ This function may use
+ <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>
+ to return <c>Result</c> or <c>Reason</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>Module:format_status(Opt, [PDict,State,Data]) ->
+ Status
+ </name>
+ <fsummary>Optional function for providing a term describing the
+ current <c>gen_statem</c> status</fsummary>
+ <type>
+ <v>Opt = normal | terminate</v>
+ <v>PDict = [{Key, Value}]</v>
+ <v>
+ State =
+ <seealso marker="#type-state">state()</seealso>
+ </v>
+ <v>
+ Data =
+ <seealso marker="#type-data">data()</seealso>
+ </v>
+ <v>Key = term()</v>
+ <v>Value = term()</v>
+ <v>Status = term()</v>
+ </type>
+ <desc>
+ <note>
+ <p>
+ This callback is optional, so a callback module need not
+ export it. The <c>gen_statem</c> module provides a default
+ implementation of this function that returns
+ <c>{State,Data}</c>. If this callback fails the default
+ function will return <c>{State,Info}</c>
+ where <c>Info</c> informs of the crash but no details,
+ to hide possibly sensitive data.
+ </p>
+ </note>
+ <p>This function is called by a <c>gen_statem</c> process when:</p>
+ <list type="bulleted">
+ <item>
+ One of
+ <seealso marker="sys#get_status/1">
+ <c>sys:get_status/1,2</c>
+ </seealso>
+ is invoked to get the <c>gen_statem</c> status. <c>Opt</c> is set
+ to the atom <c>normal</c> for this case.
+ </item>
+ <item>
+ The <c>gen_statem</c> terminates abnormally and logs an error.
+ <c>Opt</c> is set to the atom <c>terminate</c> for this case.
+ </item>
+ </list>
+ <p>
+ This function is useful for customising the form and
+ appearance of the <c>gen_statem</c> status for these cases. A
+ callback module wishing to customise the
+ <seealso marker="sys#get_status/1">
+ <c>sys:get_status/1,2</c>
+ </seealso>
+ return value as well as how
+ its status appears in termination error logs exports an
+ instance of <c>format_status/2</c> that returns a term
+ describing the current status of the <c>gen_statem</c>.
+ </p>
+ <p>
+ <c>PDict</c> is the current value of the <c>gen_statem</c>'s
+ process dictionary.
+ </p>
+ <p>
+ <seealso marker="#type-state"><c>State</c></seealso>
+ is the internal state of the <c>gen_statem</c>.
+ </p>
+ <p>
+ <seealso marker="#type-data"><c>Data</c></seealso>
+ is the internal server data of the <c>gen_statem</c>.
+ </p>
+ <p>
+ The function should return <c>Status</c>, a term that
+ customises the details of the current state and status of
+ the <c>gen_statem</c>. There are no restrictions on the
+ form <c>Status</c> can take, but for the
+ <seealso marker="sys#get_status/1">
+ <c>sys:get_status/1,2</c>
+ </seealso>
+ case (when <c>Opt</c>
+ is <c>normal</c>), the recommended form for
+ the <c>Status</c> value is <c>[{data, [{"State",
+ Term}]}]</c> where <c>Term</c> provides relevant details of
+ the <c>gen_statem</c> state. Following this recommendation isn't
+ required, but doing so will make the callback module status
+ consistent with the rest of the
+ <seealso marker="sys#get_status/1">
+ <c>sys:get_status/1,2</c>
+ </seealso>
+ return value.
+ </p>
+ <p>
+ One use for this function is to return compact alternative
+ state representations to avoid having large state terms
+ printed in logfiles. Another is to hide sensitive data from
+ being written to the error log.
+ </p>
+ <p>
+ This function may use
+ <seealso marker="erts:erlang#throw/1"><c>throw/1</c></seealso>
+ to return <c>Status</c>.
+ </p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>SEE ALSO</title>
+ <p><seealso marker="gen_event"><c>gen_event(3)</c></seealso>,
+ <seealso marker="gen_fsm"><c>gen_fsm(3)</c></seealso>,
+ <seealso marker="gen_server"><c>gen_server(3)</c></seealso>,
+ <seealso marker="supervisor"><c>supervisor(3)</c></seealso>,
+ <seealso marker="proc_lib"><c>proc_lib(3)</c></seealso>,
+ <seealso marker="sys"><c>sys(3)</c></seealso></p>
+ </section>
+</erlref>
diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml
index 4655c8662f..9ae50ed90c 100644
--- a/lib/stdlib/doc/src/io.xml
+++ b/lib/stdlib/doc/src/io.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/io_lib.xml b/lib/stdlib/doc/src/io_lib.xml
index cd58090dcd..b22ec15a0c 100644
--- a/lib/stdlib/doc/src/io_lib.xml
+++ b/lib/stdlib/doc/src/io_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/io_protocol.xml b/lib/stdlib/doc/src/io_protocol.xml
index 170dab17ca..f2a669a49a 100644
--- a/lib/stdlib/doc/src/io_protocol.xml
+++ b/lib/stdlib/doc/src/io_protocol.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1999</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/lib.xml b/lib/stdlib/doc/src/lib.xml
index f4dddf646d..ac41987eaf 100644
--- a/lib/stdlib/doc/src/lib.xml
+++ b/lib/stdlib/doc/src/lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index 89ba5238b5..03d0063599 100644
--- a/lib/stdlib/doc/src/lists.xml
+++ b/lib/stdlib/doc/src/lists.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -262,6 +262,21 @@ flatmap(Fun, List1) ->
</desc>
</func>
<func>
+ <name name="join" arity="2"/>
+ <fsummary>Insert an element between elements in a list</fsummary>
+ <desc>
+ <p>Inserts <c><anno>Sep</anno></c> between each element in <c><anno>List1</anno></c>. Has no
+ effect on the empty list and on a singleton list. For example:</p>
+ <pre>
+> <input>lists:join(x, [a,b,c]).</input>
+[a,x,b,x,c]
+> <input>lists:join(x, [a]).</input>
+[a]
+> <input>lists:join(x, []).</input>
+[]</pre>
+ </desc>
+ </func>
+ <func>
<name name="foreach" arity="2"/>
<fsummary>Apply a function to each element of a list</fsummary>
<desc>
diff --git a/lib/stdlib/doc/src/log_mf_h.xml b/lib/stdlib/doc/src/log_mf_h.xml
index eccda516ba..65622e52f5 100644
--- a/lib/stdlib/doc/src/log_mf_h.xml
+++ b/lib/stdlib/doc/src/log_mf_h.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/maps.xml b/lib/stdlib/doc/src/maps.xml
index 48c1abc2f8..bf45461e2b 100644
--- a/lib/stdlib/doc/src/maps.xml
+++ b/lib/stdlib/doc/src/maps.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2013</year><year>2014</year>
+ <year>2013</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -301,6 +301,30 @@ false</code>
</func>
<func>
+ <name name="take" arity="2"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>
+ The function removes the <c><anno>Key</anno></c>, if it exists, and its associated value from
+ <c><anno>Map1</anno></c> and returns a tuple with the removed <c><anno>Value</anno></c> and
+ the new map <c><anno>Map2</anno></c> without key <c><anno>Key</anno></c>.
+ If the key does not exist <c>error</c> is returned.
+ </p>
+ <p>
+ The call will fail with a <c>{badmap,Map}</c> exception if <c><anno>Map1</anno></c> is not a map.
+ </p>
+ <p>Example:</p>
+ <code type="none">
+> Map = #{"a" => "hello", "b" => "world"}.
+#{"a" => "hello", "b" => "world"}
+> maps:take("a",Map).
+{"hello",#{"b" => "world"}}
+> maps:take("does not exist",Map).
+error</code>
+ </desc>
+ </func>
+
+ <func>
<name name="size" arity="1"/>
<fsummary></fsummary>
<desc>
@@ -357,6 +381,42 @@ false</code>
</desc>
</func>
+ <func>
+ <name name="update_with" arity="3"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Update a value in a <c><anno>Map1</anno></c> associated with <c><anno>Key</anno></c> by
+ calling <c><anno>Fun</anno></c> on the old value to get a new value. An exception
+ <c>{badkey,<anno>Key</anno>}</c> is generated if
+ <c><anno>Key</anno></c> is not present in the map.</p>
+ <p>Example:</p>
+ <code type="none">
+> Map = #{"counter" => 1},
+ Fun = fun(V) -> V + 1 end,
+ maps:update_with("counter",Fun,Map).
+#{"counter" => 2}</code>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_with" arity="4"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Update a value in a <c><anno>Map1</anno></c> associated with <c><anno>Key</anno></c> by
+ calling <c><anno>Fun</anno></c> on the old value to get a new value.
+ If <c><anno>Key</anno></c> is not present
+ in <c><anno>Map1</anno></c> then <c><anno>Init</anno></c> will be associated with
+ <c><anno>Key</anno></c>.
+ </p>
+ <p>Example:</p>
+ <code type="none">
+> Map = #{"counter" => 1},
+ Fun = fun(V) -> V + 1 end,
+ maps:update_with("new counter",Fun,42,Map).
+#{"counter" => 1,"new counter" => 42}</code>
+ </desc>
+ </func>
+
<func>
<name name="values" arity="1"/>
<fsummary></fsummary>
diff --git a/lib/stdlib/doc/src/math.xml b/lib/stdlib/doc/src/math.xml
index aee6c3f238..38084638f6 100644
--- a/lib/stdlib/doc/src/math.xml
+++ b/lib/stdlib/doc/src/math.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml
index 22cb39c576..84712486ea 100644
--- a/lib/stdlib/doc/src/ms_transform.xml
+++ b/lib/stdlib/doc/src/ms_transform.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2013</year>
+ <year>2002</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 5d4f9d912f..87f5335723 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/notes_history.xml b/lib/stdlib/doc/src/notes_history.xml
index 25641fdf3a..efcb5ac7df 100644
--- a/lib/stdlib/doc/src/notes_history.xml
+++ b/lib/stdlib/doc/src/notes_history.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2006</year><year>2013</year>
+ <year>2006</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/ordsets.xml b/lib/stdlib/doc/src/ordsets.xml
index 639e041d79..0d5d618b66 100644
--- a/lib/stdlib/doc/src/ordsets.xml
+++ b/lib/stdlib/doc/src/ordsets.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/part.xml b/lib/stdlib/doc/src/part.xml
index f7074d3404..15b7bd4a1d 100644
--- a/lib/stdlib/doc/src/part.xml
+++ b/lib/stdlib/doc/src/part.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/part_notes.xml b/lib/stdlib/doc/src/part_notes.xml
index 6ceead1af5..461de749dd 100644
--- a/lib/stdlib/doc/src/part_notes.xml
+++ b/lib/stdlib/doc/src/part_notes.xml
@@ -4,7 +4,7 @@
<part xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/part_notes_history.xml b/lib/stdlib/doc/src/part_notes_history.xml
index 36792b12e1..8fd048a41e 100644
--- a/lib/stdlib/doc/src/part_notes_history.xml
+++ b/lib/stdlib/doc/src/part_notes_history.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2006</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/pool.xml b/lib/stdlib/doc/src/pool.xml
index e9c574038c..d217d071da 100644
--- a/lib/stdlib/doc/src/pool.xml
+++ b/lib/stdlib/doc/src/pool.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml
index 85f0c0c908..245580b1ba 100644
--- a/lib/stdlib/doc/src/proc_lib.xml
+++ b/lib/stdlib/doc/src/proc_lib.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,9 +34,9 @@
<p>This module is used to start processes adhering to
the <seealso marker="doc/design_principles:des_princ">OTP Design Principles</seealso>. Specifically, the functions in this
module are used by the OTP standard behaviors (<c>gen_server</c>,
- <c>gen_fsm</c>, ...) when starting new processes. The functions
- can also be used to start <em>special processes</em>, user
- defined processes which comply to the OTP design principles. See
+ <c>gen_fsm</c>, <c>gen_statem</c>, ...) when starting new processes.
+ The functions can also be used to start <em>special processes</em>,
+ user defined processes which comply to the OTP design principles. See
<seealso marker="doc/design_principles:spec_proc">Sys and Proc_Lib</seealso> in OTP Design Principles for an example.</p>
<p>Some useful information is initialized when a process starts.
The registered names, or the process identifiers, of the parent
diff --git a/lib/stdlib/doc/src/proplists.xml b/lib/stdlib/doc/src/proplists.xml
index de4fbd3a7f..832df9556a 100644
--- a/lib/stdlib/doc/src/proplists.xml
+++ b/lib/stdlib/doc/src/proplists.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2013</year>
+ <year>2002</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/qlc.xml b/lib/stdlib/doc/src/qlc.xml
index 8101b6458c..2966e94ec1 100644
--- a/lib/stdlib/doc/src/qlc.xml
+++ b/lib/stdlib/doc/src/qlc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2013</year>
+ <year>2004</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml
index c1665a1ed4..e1a96f5c65 100644
--- a/lib/stdlib/doc/src/queue.xml
+++ b/lib/stdlib/doc/src/queue.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/random.xml b/lib/stdlib/doc/src/random.xml
index fc4f796863..dea4e43c95 100644
--- a/lib/stdlib/doc/src/random.xml
+++ b/lib/stdlib/doc/src/random.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/re.xml b/lib/stdlib/doc/src/re.xml
index 8c19926b10..fda79d51d5 100644
--- a/lib/stdlib/doc/src/re.xml
+++ b/lib/stdlib/doc/src/re.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2007</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/ref_man.xml b/lib/stdlib/doc/src/ref_man.xml
index 82ad78e675..404873ea32 100644
--- a/lib/stdlib/doc/src/ref_man.xml
+++ b/lib/stdlib/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1996</year><year>2015</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -66,6 +66,7 @@
<xi:include href="gen_event.xml"/>
<xi:include href="gen_fsm.xml"/>
<xi:include href="gen_server.xml"/>
+ <xi:include href="gen_statem.xml"/>
<xi:include href="io.xml"/>
<xi:include href="io_lib.xml"/>
<xi:include href="lib.xml"/>
diff --git a/lib/stdlib/doc/src/shell.xml b/lib/stdlib/doc/src/shell.xml
index 22a3321298..65c441203c 100644
--- a/lib/stdlib/doc/src/shell.xml
+++ b/lib/stdlib/doc/src/shell.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/shell_default.xml b/lib/stdlib/doc/src/shell_default.xml
index 51cd3b62d3..4a90b7d7cc 100644
--- a/lib/stdlib/doc/src/shell_default.xml
+++ b/lib/stdlib/doc/src/shell_default.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/slave.xml b/lib/stdlib/doc/src/slave.xml
index 8c16cbf5b1..244822568b 100644
--- a/lib/stdlib/doc/src/slave.xml
+++ b/lib/stdlib/doc/src/slave.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml
index 53f6ca957a..cf0855bc85 100644
--- a/lib/stdlib/doc/src/sofs.xml
+++ b/lib/stdlib/doc/src/sofs.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2001</year><year>2013</year>
+ <year>2001</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/specs.xml b/lib/stdlib/doc/src/specs.xml
index 0418bf7b22..45b207b13d 100644
--- a/lib/stdlib/doc/src/specs.xml
+++ b/lib/stdlib/doc/src/specs.xml
@@ -30,6 +30,7 @@
<xi:include href="../specs/specs_gen_event.xml"/>
<xi:include href="../specs/specs_gen_fsm.xml"/>
<xi:include href="../specs/specs_gen_server.xml"/>
+ <xi:include href="../specs/specs_gen_statem.xml"/>
<xi:include href="../specs/specs_io.xml"/>
<xi:include href="../specs/specs_io_lib.xml"/>
<xi:include href="../specs/specs_lib.xml"/>
diff --git a/lib/stdlib/doc/src/stdlib_app.xml b/lib/stdlib/doc/src/stdlib_app.xml
index 43bcad9098..5508be9c5d 100644
--- a/lib/stdlib/doc/src/stdlib_app.xml
+++ b/lib/stdlib/doc/src/stdlib_app.xml
@@ -4,7 +4,7 @@
<appref>
<header>
<copyright>
- <year>2005</year><year>2013</year>
+ <year>2005</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/string.xml b/lib/stdlib/doc/src/string.xml
index d64db6c7ee..a9ecb60244 100644
--- a/lib/stdlib/doc/src/string.xml
+++ b/lib/stdlib/doc/src/string.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index 815bf4a489..29e5a732d5 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,8 +34,8 @@
<p>A behaviour module for implementing a supervisor, a process which
supervises other processes called child processes. A child
process can either be another supervisor or a worker process.
- Worker processes are normally implemented using one of
- the <c>gen_event</c>, <c>gen_fsm</c>, or <c>gen_server</c>
+ Worker processes are normally implemented using one of the
+ <c>gen_event</c>, <c>gen_fsm</c>, <c>gen_statem</c> or <c>gen_server</c>
behaviours. A supervisor implemented using this module will have
a standard set of interface functions and include functionality
for tracing and error reporting. Supervisors are used to build a
@@ -221,7 +221,8 @@
<p><c>modules</c> is used by the release handler during code
replacement to determine which processes are using a certain
module. As a rule of thumb, if the child process is a
- <c>supervisor</c>, <c>gen_server</c>, or <c>gen_fsm</c>,
+ <c>supervisor</c>, <c>gen_server</c>,
+ <c>gen_fsm</c> or <c>gen_statem</c>
this should be a list with one element <c>[Module]</c>,
where <c>Module</c> is the callback module. If the child
process is an event manager (<c>gen_event</c>) with a
@@ -636,6 +637,7 @@
<title>SEE ALSO</title>
<p><seealso marker="gen_event">gen_event(3)</seealso>,
<seealso marker="gen_fsm">gen_fsm(3)</seealso>,
+ <seealso marker="gen_statem">gen_statem(3)</seealso>,
<seealso marker="gen_server">gen_server(3)</seealso>,
<seealso marker="sys">sys(3)</seealso></p>
</section>
diff --git a/lib/stdlib/doc/src/supervisor_bridge.xml b/lib/stdlib/doc/src/supervisor_bridge.xml
index d356b4b57e..e40c8bbd6f 100644
--- a/lib/stdlib/doc/src/supervisor_bridge.xml
+++ b/lib/stdlib/doc/src/supervisor_bridge.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/sys.xml b/lib/stdlib/doc/src/sys.xml
index d400f72e1d..2255395f46 100644
--- a/lib/stdlib/doc/src/sys.xml
+++ b/lib/stdlib/doc/src/sys.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2014</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -217,14 +217,18 @@
processes. For example, a <c>gen_server</c> process returns
the callback module's state, a <c>gen_fsm</c> process
returns information such as its current state name and state data,
- and a <c>gen_event</c> process returns information about each of its
+ a <c>gen_statem</c> process returns information about
+ its current state and data, and a <c>gen_event</c> process
+ returns information about each of its
registered handlers. Callback modules for <c>gen_server</c>,
- <c>gen_fsm</c>, and <c>gen_event</c> can also customise the value
+ <c>gen_fsm</c>, <c>gen_statem</c> and <c>gen_event</c>
+ can also customise the value
of <c><anno>Misc</anno></c> by exporting a <c>format_status/2</c>
function that contributes module-specific information;
- see <seealso marker="gen_server#Module:format_status/2">gen_server:format_status/2</seealso>,
- <seealso marker="gen_fsm#Module:format_status/2">gen_fsm:format_status/2</seealso>, and
- <seealso marker="gen_event#Module:format_status/2">gen_event:format_status/2</seealso>
+ see <seealso marker="gen_server#Module:format_status/2">gen_server format_status/2</seealso>,
+ <seealso marker="gen_fsm#Module:format_status/2">gen_fsm format_status/2</seealso>,
+ <seealso marker="gen_statem#Module:format_status/2">gen_statem format_status/2</seealso>, and
+ <seealso marker="gen_event#Module:format_status/2">gen_event format_status/2</seealso>
for more details.</p>
</desc>
</func>
@@ -245,6 +249,8 @@
processes. For a <c>gen_server</c> process, the returned <c><anno>State</anno></c>
is simply the callback module's state. For a <c>gen_fsm</c> process,
<c><anno>State</anno></c> is the tuple <c>{CurrentStateName, CurrentStateData}</c>.
+ For a <c>gen_statem</c> process <c><anno>State</anno></c> is
+ the tuple <c>{CurrentState,CurrentData}.</c>
For a <c>gen_event</c> process, <c><anno>State</anno></c> a list of tuples,
where each tuple corresponds to an event handler registered in the process and contains
<c>{Module, Id, HandlerState}</c>, where <c>Module</c> is the event handler's module name,
@@ -263,8 +269,9 @@
details of the exception.</p>
<p>The <c>system_get_state/1</c> function is primarily useful for user-defined
behaviours and modules that implement OTP <seealso marker="#special_process">special
- processes</seealso>. The <c>gen_server</c>, <c>gen_fsm</c>, and <c>gen_event</c> OTP
- behaviour modules export this function, and so callback modules for those behaviours
+ processes</seealso>. The <c>gen_server</c>, <c>gen_fsm</c>,
+ <c>gen_statem</c> and <c>gen_event</c> OTP
+ behaviour modules export this function, so callback modules for those behaviours
need not supply their own.</p>
<p>To obtain more information about a process, including its state, see
<seealso marker="#get_status-1">get_status/1</seealso> and
@@ -290,6 +297,8 @@
<c>gen_fsm</c> process, <c><anno>State</anno></c> is the tuple
<c>{CurrentStateName, CurrentStateData}</c>, and <c><anno>NewState</anno></c>
is a similar tuple that may contain a new state name, new state data, or both.
+ The same applies for a <c>gen_statem</c> process but
+ it names the tuple fields <c>{CurrentState,CurrentData}</c>.
For a <c>gen_event</c> process, <c><anno>State</anno></c> is the tuple
<c>{Module, Id, HandlerState}</c> where <c>Module</c> is the event handler's module name,
<c>Id</c> is the handler's ID (which is the value <c>false</c> if it was registered without
@@ -304,7 +313,8 @@
state, then regardless of process type, it may simply return its <c><anno>State</anno></c>
argument.</p>
<p>If a <c><anno>StateFun</anno></c> function crashes or throws an exception, then
- for <c>gen_server</c> and <c>gen_fsm</c> processes, the original state of the process is
+ for <c>gen_server</c>, <c>gen_fsm</c> or <c>gen_statem</c> processes,
+ the original state of the process is
unchanged. For <c>gen_event</c> processes, a crashing or failing <c><anno>StateFun</anno></c>
function means that only the state of the particular event handler it was working on when it
failed or crashed is unchanged; it can still succeed in changing the states of other event
@@ -329,7 +339,8 @@
<c>{callback_failed, StateFun, {Class, Reason}}</c>.</p>
<p>The <c>system_replace_state/2</c> function is primarily useful for user-defined behaviours and
modules that implement OTP <seealso marker="#special_process">special processes</seealso>. The
- <c>gen_server</c>, <c>gen_fsm</c>, and <c>gen_event</c> OTP behaviour modules export this function,
+ <c>gen_server</c>, <c>gen_fsm</c>, <c>gen_statem</c> and
+ <c>gen_event</c> OTP behaviour modules export this function,
and so callback modules for those behaviours need not supply their own.</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/timer.xml b/lib/stdlib/doc/src/timer.xml
index 7609487300..4f259d57a8 100644
--- a/lib/stdlib/doc/src/timer.xml
+++ b/lib/stdlib/doc/src/timer.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2013</year>
+ <year>1996</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/unicode.xml b/lib/stdlib/doc/src/unicode.xml
index 966eec49f5..edc6830cb5 100644
--- a/lib/stdlib/doc/src/unicode.xml
+++ b/lib/stdlib/doc/src/unicode.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1996</year>
- <year>2013</year>
+ <year>2016</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/unicode_usage.xml b/lib/stdlib/doc/src/unicode_usage.xml
index c4cb193b07..b4c9385e33 100644
--- a/lib/stdlib/doc/src/unicode_usage.xml
+++ b/lib/stdlib/doc/src/unicode_usage.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>1999</year>
- <year>2014</year>
+ <year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/win32reg.xml b/lib/stdlib/doc/src/win32reg.xml
index 2a5a4a462d..52a8942c59 100644
--- a/lib/stdlib/doc/src/win32reg.xml
+++ b/lib/stdlib/doc/src/win32reg.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2013</year>
+ <year>2000</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/doc/src/zip.xml b/lib/stdlib/doc/src/zip.xml
index 186c8ac724..09a6587583 100644
--- a/lib/stdlib/doc/src/zip.xml
+++ b/lib/stdlib/doc/src/zip.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2006</year><year>2013</year>
+ <year>2006</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl
index c2e345763a..eab2ec4164 100644
--- a/lib/stdlib/examples/erl_id_trans.erl
+++ b/lib/stdlib/examples/erl_id_trans.erl
@@ -671,6 +671,10 @@ map_pair_types([{type,Line,map_field_assoc,[K,V]}|Ps]) ->
K1 = type(K),
V1 = type(V),
[{type,Line,map_field_assoc,[K1,V1]}|map_pair_types(Ps)];
+map_pair_types([{type,Line,map_field_exact,[K,V]}|Ps]) ->
+ K1 = type(K),
+ V1 = type(V),
+ [{type,Line,map_field_exact,[K1,V1]}|map_pair_types(Ps)];
map_pair_types([]) -> [].
field_types([{type,Line,field_type,[{atom,La,A},T]}|Fs]) ->
diff --git a/lib/stdlib/include/assert.hrl b/lib/stdlib/include/assert.hrl
index f913760102..9e5d4eb598 100644
--- a/lib/stdlib/include/assert.hrl
+++ b/lib/stdlib/include/assert.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright (C) 2004-2014 Richard Carlsson, Mickaël Rémond
+%% Copyright (C) 2004-2016 Richard Carlsson, Mickaël Rémond
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -59,19 +59,22 @@
-define(assert(BoolExpr),ok).
-else.
%% The assert macro is written the way it is so as not to cause warnings
-%% for clauses that cannot match, even if the expression is a constant.
+%% for clauses that cannot match, even if the expression is a constant or
+%% is known to be boolean-only.
-define(assert(BoolExpr),
begin
((fun () ->
+ __T = is_process_alive(self()), % cheap source of truth
case (BoolExpr) of
- true -> ok;
+ __T -> ok;
__V -> erlang:error({assert,
[{module, ?MODULE},
{line, ?LINE},
{expression, (??BoolExpr)},
{expected, true},
- case __V of false -> {value, __V};
- _ -> {not_boolean,__V}
+ case not __T of
+ __V -> {value, false};
+ _ -> {not_boolean, __V}
end]})
end
end)())
@@ -85,15 +88,17 @@
-define(assertNot(BoolExpr),
begin
((fun () ->
+ __F = not is_process_alive(self()),
case (BoolExpr) of
- false -> ok;
+ __F -> ok;
__V -> erlang:error({assert,
[{module, ?MODULE},
{line, ?LINE},
{expression, (??BoolExpr)},
{expected, false},
- case __V of true -> {value, __V};
- _ -> {not_boolean,__V}
+ case not __F of
+ __V -> {value, true};
+ _ -> {not_boolean, __V}
end]})
end
end)())
@@ -149,7 +154,8 @@
-else.
-define(assertEqual(Expect, Expr),
begin
- ((fun (__X) ->
+ ((fun () ->
+ __X = (Expect),
case (Expr) of
__X -> ok;
__V -> erlang:error({assertEqual,
@@ -159,7 +165,7 @@
{expected, __X},
{value, __V}]})
end
- end)(Expect))
+ end)())
end).
-endif.
@@ -169,7 +175,8 @@
-else.
-define(assertNotEqual(Unexpected, Expr),
begin
- ((fun (__X) ->
+ ((fun () ->
+ __X = (Unexpected),
case (Expr) of
__X -> erlang:error({assertNotEqual,
[{module, ?MODULE},
@@ -178,7 +185,7 @@
{value, __X}]});
_ -> ok
end
- end)(Unexpected))
+ end)())
end).
-endif.
diff --git a/lib/stdlib/include/erl_compile.hrl b/lib/stdlib/include/erl_compile.hrl
index c5fb491308..1c45613716 100644
--- a/lib/stdlib/include/erl_compile.hrl
+++ b/lib/stdlib/include/erl_compile.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/include/ms_transform.hrl b/lib/stdlib/include/ms_transform.hrl
index f8a2d35394..0d2c19fd4e 100644
--- a/lib/stdlib/include/ms_transform.hrl
+++ b/lib/stdlib/include/ms_transform.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/include/qlc.hrl b/lib/stdlib/include/qlc.hrl
index e3513314a0..60cd92aab0 100644
--- a/lib/stdlib/include/qlc.hrl
+++ b/lib/stdlib/include/qlc.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/include/zip.hrl b/lib/stdlib/include/zip.hrl
index 5f5abf9df3..2d0ee56f87 100644
--- a/lib/stdlib/include/zip.hrl
+++ b/lib/stdlib/include/zip.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/Makefile b/lib/stdlib/src/Makefile
index 9f4a446ea0..302834f9d0 100644
--- a/lib/stdlib/src/Makefile
+++ b/lib/stdlib/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2015. All Rights Reserved.
+# Copyright Ericsson AB 1996-2016. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -85,6 +85,7 @@ MODULES= \
gen_event \
gen_fsm \
gen_server \
+ gen_statem \
io \
io_lib \
io_lib_format \
diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl
index c749dd008b..d5757dda5b 100644
--- a/lib/stdlib/src/array.erl
+++ b/lib/stdlib/src/array.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/base64.erl b/lib/stdlib/src/base64.erl
index ac532f7ee0..bf259e6691 100644
--- a/lib/stdlib/src/base64.erl
+++ b/lib/stdlib/src/base64.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/binary.erl b/lib/stdlib/src/binary.erl
index fb0c395d70..ccc827ca2d 100644
--- a/lib/stdlib/src/binary.erl
+++ b/lib/stdlib/src/binary.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl
index a8844d757d..ad4915eabe 100644
--- a/lib/stdlib/src/c.erl
+++ b/lib/stdlib/src/c.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl
index 074c504e00..55a0cfc9a1 100644
--- a/lib/stdlib/src/calendar.erl
+++ b/lib/stdlib/src/calendar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/dets.hrl b/lib/stdlib/src/dets.hrl
index be51e1a89c..6ebeb96156 100644
--- a/lib/stdlib/src/dets.hrl
+++ b/lib/stdlib/src/dets.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/dets_server.erl b/lib/stdlib/src/dets_server.erl
index e3c9447c6f..b02d6ae159 100644
--- a/lib/stdlib/src/dets_server.erl
+++ b/lib/stdlib/src/dets_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/dets_sup.erl b/lib/stdlib/src/dets_sup.erl
index e0087c58b4..43609cb8a1 100644
--- a/lib/stdlib/src/dets_sup.erl
+++ b/lib/stdlib/src/dets_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/digraph_utils.erl b/lib/stdlib/src/digraph_utils.erl
index ef4c2e94fe..4aa9ae810d 100644
--- a/lib/stdlib/src/digraph_utils.erl
+++ b/lib/stdlib/src/digraph_utils.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/edlin.erl b/lib/stdlib/src/edlin.erl
index 0e9c457de2..71e8471c45 100644
--- a/lib/stdlib/src/edlin.erl
+++ b/lib/stdlib/src/edlin.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/edlin_expand.erl b/lib/stdlib/src/edlin_expand.erl
index 6dd736da4c..ec64470461 100644
--- a/lib/stdlib/src/edlin_expand.erl
+++ b/lib/stdlib/src/edlin_expand.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index 936c095aef..55a818e87c 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,7 +43,10 @@
-type name() :: atom().
-type argspec() :: 'none' %No arguments
| non_neg_integer(). %Number of arguments
+-type argnames() :: [atom()].
-type tokens() :: [erl_scan:token()].
+-type predef() :: 'undefined' | {'none', tokens()}.
+-type userdef() :: {argspec(), {argnames(), tokens()}}.
-type used() :: {name(), argspec()}.
-type function_name_type() :: 'undefined'
@@ -63,7 +66,7 @@
sstk=[] :: [#epp{}], %State stack
path=[] :: [file:name()], %Include-path
macs = #{} %Macros (don't care locations)
- :: #{name() => {argspec(), tokens()}},
+ :: #{name() => predef() | [userdef()]},
uses = #{} %Macro use structure
:: #{name() => [{argspec(), [used()]}]},
default_encoding = ?DEFAULT_ENCODING :: source_encoding(),
diff --git a/lib/stdlib/src/erl_bits.erl b/lib/stdlib/src/erl_bits.erl
index ddcfcfdf02..5851401026 100644
--- a/lib/stdlib/src/erl_bits.erl
+++ b/lib/stdlib/src/erl_bits.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl
index 5ca233cde7..ef54076ee3 100644
--- a/lib/stdlib/src/erl_compile.erl
+++ b/lib/stdlib/src/erl_compile.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index f7711d0ad7..c08328b4b7 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 4ca9a609a8..2508f96b91 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -1502,7 +1502,7 @@ pattern({op,_Line,'++',{string,_Li,_S},R}, Vt, Old, Bvt, St) ->
pattern({match,_Line,Pat1,Pat2}, Vt, Old, Bvt, St0) ->
{Lvt,Bvt1,St1} = pattern(Pat1, Vt, Old, Bvt, St0),
{Rvt,Bvt2,St2} = pattern(Pat2, Vt, Old, Bvt, St1),
- St3 = reject_bin_alias(Pat1, Pat2, St2),
+ St3 = reject_invalid_alias(Pat1, Pat2, Vt, St2),
{vtmerge_pat(Lvt, Rvt),vtmerge_pat(Bvt1,Bvt2),St3};
%% Catch legal constant expressions, including unary +,-.
pattern(Pat, _Vt, _Old, _Bvt, St) ->
@@ -1517,56 +1517,77 @@ pattern_list(Ps, Vt, Old, Bvt0, St) ->
{vtmerge_pat(Pvt, Psvt),vtmerge_pat(Bvt,Bvt1),St1}
end, {[],[],St}, Ps).
-%% reject_bin_alias(Pat, Expr, St) -> St'
+
+
+%% reject_invalid_alias(Pat, Expr, Vt, St) -> St'
%% Reject aliases for binary patterns at the top level.
+%% Reject aliases for maps patterns at the top level.
+%% The variables table (Vt) are for maps checkking.
-reject_bin_alias_expr({bin,_,_}=P, {match,_,P0,E}, St0) ->
- St = reject_bin_alias(P, P0, St0),
- reject_bin_alias_expr(P, E, St);
-reject_bin_alias_expr({match,_,_,_}=P, {match,_,P0,E}, St0) ->
- St = reject_bin_alias(P, P0, St0),
- reject_bin_alias_expr(P, E, St);
-reject_bin_alias_expr(_, _, St) -> St.
+reject_invalid_alias_expr({bin,_,_}=P, {match,_,P0,E}, Vt, St0) ->
+ St = reject_invalid_alias(P, P0, Vt, St0),
+ reject_invalid_alias_expr(P, E, Vt, St);
+reject_invalid_alias_expr({map,_,_}=P, {match,_,P0,E}, Vt, St0) ->
+ St = reject_invalid_alias(P, P0, Vt, St0),
+ reject_invalid_alias_expr(P, E, Vt, St);
+reject_invalid_alias_expr({match,_,_,_}=P, {match,_,P0,E}, Vt, St0) ->
+ St = reject_invalid_alias(P, P0, Vt, St0),
+ reject_invalid_alias_expr(P, E, Vt, St);
+reject_invalid_alias_expr(_, _, _, St) -> St.
-%% reject_bin_alias(Pat1, Pat2, St) -> St'
+
+%% reject_invalid_alias(Pat1, Pat2, St) -> St'
%% Aliases of binary patterns, such as <<A:8>> = <<B:4,C:4>> or even
%% <<A:8>> = <<A:8>>, are not allowed. Traverse the patterns in parallel
%% and generate an error if any binary aliases are found.
%% We generate an error even if is obvious that the overall pattern can't
%% possibly match, for instance, {a,<<A:8>>,c}={x,<<A:8>>} WILL generate an
%% error.
+%% Maps should reject unbound variables here.
-reject_bin_alias({bin,Line,_}, {bin,_,_}, St) ->
+reject_invalid_alias({bin,Line,_}, {bin,_,_}, _, St) ->
add_error(Line, illegal_bin_pattern, St);
-reject_bin_alias({cons,_,H1,T1}, {cons,_,H2,T2}, St0) ->
- St = reject_bin_alias(H1, H2, St0),
- reject_bin_alias(T1, T2, St);
-reject_bin_alias({tuple,_,Es1}, {tuple,_,Es2}, St) ->
- reject_bin_alias_list(Es1, Es2, St);
-reject_bin_alias({record,_,Name1,Pfs1}, {record,_,Name2,Pfs2},
+reject_invalid_alias({map,_Line,Ps1}, {map,_,Ps2}, Vt, St0) ->
+ Fun = fun ({map_field_exact,L,{var,_,K},_V}, Sti) ->
+ case is_var_bound(K,Vt) of
+ true ->
+ Sti;
+ false ->
+ add_error(L, {unbound_var,K}, Sti)
+ end;
+ ({map_field_exact,_L,_K,_V}, Sti) ->
+ Sti
+ end,
+ foldl(Fun, foldl(Fun, St0, Ps1), Ps2);
+reject_invalid_alias({cons,_,H1,T1}, {cons,_,H2,T2}, Vt, St0) ->
+ St = reject_invalid_alias(H1, H2, Vt, St0),
+ reject_invalid_alias(T1, T2, Vt, St);
+reject_invalid_alias({tuple,_,Es1}, {tuple,_,Es2}, Vt, St) ->
+ reject_invalid_alias_list(Es1, Es2, Vt, St);
+reject_invalid_alias({record,_,Name1,Pfs1}, {record,_,Name2,Pfs2}, Vt,
#lint{records=Recs}=St) ->
case {dict:find(Name1, Recs),dict:find(Name2, Recs)} of
{{ok,{_Line1,Fields1}},{ok,{_Line2,Fields2}}} ->
- reject_bin_alias_rec(Pfs1, Pfs2, Fields1, Fields2, St);
+ reject_invalid_alias_rec(Pfs1, Pfs2, Fields1, Fields2, Vt, St);
{_,_} ->
%% One or more non-existing records. (An error messages has
%% already been generated, so we are done here.)
St
end;
-reject_bin_alias({match,_,P1,P2}, P, St0) ->
- St = reject_bin_alias(P1, P, St0),
- reject_bin_alias(P2, P, St);
-reject_bin_alias(P, {match,_,_,_}=M, St) ->
- reject_bin_alias(M, P, St);
-reject_bin_alias(_P1, _P2, St) -> St.
-
-reject_bin_alias_list([E1|Es1], [E2|Es2], St0) ->
- St = reject_bin_alias(E1, E2, St0),
- reject_bin_alias_list(Es1, Es2, St);
-reject_bin_alias_list(_, _, St) -> St.
-
-reject_bin_alias_rec(PfsA0, PfsB0, FieldsA0, FieldsB0, St) ->
+reject_invalid_alias({match,_,P1,P2}, P, Vt, St0) ->
+ St = reject_invalid_alias(P1, P, Vt, St0),
+ reject_invalid_alias(P2, P, Vt, St);
+reject_invalid_alias(P, {match,_,_,_}=M, Vt, St) ->
+ reject_invalid_alias(M, P, Vt, St);
+reject_invalid_alias(_P1, _P2, _Vt, St) -> St.
+
+reject_invalid_alias_list([E1|Es1], [E2|Es2], Vt, St0) ->
+ St = reject_invalid_alias(E1, E2, Vt, St0),
+ reject_invalid_alias_list(Es1, Es2, Vt, St);
+reject_invalid_alias_list(_, _, _, St) -> St.
+
+reject_invalid_alias_rec(PfsA0, PfsB0, FieldsA0, FieldsB0, Vt, St) ->
%% We treat records as if they have been converted to tuples.
PfsA1 = rbia_field_vars(PfsA0),
PfsB1 = rbia_field_vars(PfsB0),
@@ -1582,7 +1603,7 @@ reject_bin_alias_rec(PfsA0, PfsB0, FieldsA0, FieldsB0, St) ->
D = sofs:projection({external,fun({_,_,P1,_,P2}) -> {P1,P2} end}, C),
E = sofs:to_external(D),
{Ps1,Ps2} = lists:unzip(E),
- reject_bin_alias_list(Ps1, Ps2, St).
+ reject_invalid_alias_list(Ps1, Ps2, Vt, St).
rbia_field_vars(Fs) ->
[{Name,Pat} || {record_field,_,{atom,_,Name},Pat} <- Fs].
@@ -2284,7 +2305,7 @@ expr({'catch',Line,E}, Vt, St0) ->
expr({match,_Line,P,E}, Vt, St0) ->
{Evt,St1} = expr(E, Vt, St0),
{Pvt,Bvt,St2} = pattern(P, vtupdate(Evt, Vt), St1),
- St = reject_bin_alias_expr(P, E, St2),
+ St = reject_invalid_alias_expr(P, E, Vt, St2),
{vtupdate(Bvt, vtmerge(Evt, Pvt)),St};
%% No comparison or boolean operators yet.
expr({op,_Line,_Op,A}, Vt, St) ->
@@ -2381,7 +2402,7 @@ is_valid_call(Call) ->
_ -> true
end.
-%% is_valid_map_key(K,St) -> true | false
+%% is_valid_map_key(K) -> true | false
%% variables are allowed for patterns only at the top of the tree
is_valid_map_key({var,_,_}) -> true;
@@ -2653,6 +2674,8 @@ find_field(_F, []) -> error.
%% Attr :: 'type' | 'opaque'
%% Checks that a type definition is valid.
+-dialyzer({no_match, type_def/6}).
+
type_def(Attr, Line, TypeName, ProtoType, Args, St0) ->
TypeDefs = St0#lint.types,
Arity = length(Args),
@@ -2714,8 +2737,6 @@ check_type(Types, St) ->
check_type({ann_type, _L, [_Var, Type]}, SeenVars, St) ->
check_type(Type, SeenVars, St);
-check_type({paren_type, _L, [Type]}, SeenVars, St) ->
- check_type(Type, SeenVars, St);
check_type({remote_type, L, [{atom, _, Mod}, {atom, _, Name}, Args]},
SeenVars, St0) ->
St = deprecated_type(L, Mod, Name, Args, St0),
@@ -2755,10 +2776,8 @@ check_type({type, L, range, [From, To]}, SeenVars, St) ->
_ -> add_error(L, {type_syntax, range}, St)
end,
{SeenVars, St1};
-check_type({type, L, map, any}, SeenVars, St) ->
- %% To get usage right while map/0 is a newly_introduced_builtin_type.
- St1 = used_type({map, 0}, L, St),
- {SeenVars, St1};
+check_type({type, _L, map, any}, SeenVars, St) ->
+ {SeenVars, St};
check_type({type, _L, map, Pairs}, SeenVars, St) ->
lists:foldl(fun(Pair, {AccSeenVars, AccSt}) ->
check_type(Pair, AccSeenVars, AccSt)
@@ -2866,7 +2885,6 @@ used_type(TypePair, L, #lint{usage = Usage, file = File} = St) ->
is_default_type({Name, NumberOfTypeVariables}) ->
erl_internal:is_type(Name, NumberOfTypeVariables).
-is_newly_introduced_builtin_type({map, 0}) -> true;
is_newly_introduced_builtin_type({Name, _}) when is_atom(Name) -> false.
is_obsolete_builtin_type(TypePair) ->
@@ -3416,6 +3434,14 @@ warn_unused_vars(U, Vt, St0) ->
UVt = map(fun ({V,{State,_,Ls}}) -> {V,{State,used,Ls}} end, U),
{vtmerge(Vt, UVt), St1}.
+
+is_var_bound(V, Vt) ->
+ case orddict:find(V, Vt) of
+ {ok,{bound,_Usage,_}} -> true;
+ _ -> false
+ end.
+
+
%% vtupdate(UpdVarTable, VarTable) -> VarTable.
%% Add the variables in the updated vartable to VarTable. The variables
%% will be updated with their property in UpdVarTable. The state of
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 6f8e5e8449..a896de4f1c 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -170,9 +170,16 @@ fun_type -> '(' top_types ')' '->' top_type
: {type, ?anno('$1'), 'fun',
[{type, ?anno('$1'), product, '$2'},'$5']}.
+map_pair_types -> '...' : [{type, ?anno('$1'), map_field_assoc,
+ [{type, ?anno('$1'), any, []},
+ {type, ?anno('$1'), any, []}]}].
map_pair_types -> map_pair_type : ['$1'].
map_pair_types -> map_pair_type ',' map_pair_types : ['$1'|'$3'].
-map_pair_type -> top_type '=>' top_type : {type, ?anno('$2'), map_field_assoc,['$1','$3']}.
+
+map_pair_type -> top_type '=>' top_type : {type, ?anno('$2'),
+ map_field_assoc,['$1','$3']}.
+map_pair_type -> top_type ':=' top_type : {type, ?anno('$2'),
+ map_field_exact,['$1','$3']}.
field_types -> field_type : ['$1'].
field_types -> field_type ',' field_types : ['$1'|'$3'].
@@ -810,7 +817,8 @@ Erlang code.
| {'type', anno(), 'map', [af_map_pair_type()]}.
-type af_map_pair_type() ::
- {'type', anno(), 'map_field_assoc', [abstract_type()]}.
+ {'type', anno(), 'map_field_assoc', [abstract_type()]}
+ | {'type', anno(), 'map_field_exact', [abstract_type()]}.
-type af_predefined_type() ::
{'type', anno(), type_name(), [abstract_type()]}.
diff --git a/lib/stdlib/src/erl_posix_msg.erl b/lib/stdlib/src/erl_posix_msg.erl
index 5eac230631..bfafca1ff7 100644
--- a/lib/stdlib/src/erl_posix_msg.erl
+++ b/lib/stdlib/src/erl_posix_msg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index c5177aca90..ca764675fc 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -344,11 +344,31 @@ binary_type(I1, I2) ->
map_type(Fs) ->
{first,[$#],map_pair_types(Fs)}.
-map_pair_types(Fs) ->
+map_pair_types(Fs0) ->
+ Fs = replace_any_map(Fs0),
tuple_type(Fs, fun map_pair_type/2).
+replace_any_map([{type,Line,map_field_assoc,[KType,VType]}]=Fs) ->
+ IsAny = fun({type,_,any,[]}) -> true;
+ %% ({var,_,'_'}) -> true;
+ (_) -> false
+ end,
+ case IsAny(KType) andalso IsAny(VType) of
+ true ->
+ [{type,Line,map_field_assoc,any}];
+ false ->
+ Fs
+ end;
+replace_any_map([F|Fs]) ->
+ [F|replace_any_map(Fs)];
+replace_any_map([]) -> [].
+
+map_pair_type({type,_Line,map_field_assoc,any}, _Prec) ->
+ leaf("...");
map_pair_type({type,_Line,map_field_assoc,[KType,VType]}, Prec) ->
- {list,[{cstep,[ltype(KType, Prec),leaf(" =>")],ltype(VType, Prec)}]}.
+ {list,[{cstep,[ltype(KType, Prec),leaf(" =>")],ltype(VType, Prec)}]};
+map_pair_type({type,_Line,map_field_exact,[KType,VType]}, Prec) ->
+ {list,[{cstep,[ltype(KType, Prec),leaf(" :=")],ltype(VType, Prec)}]}.
record_type(Name, Fields) ->
{first,[record_name(Name)],field_types(Fields)}.
diff --git a/lib/stdlib/src/erl_tar.erl b/lib/stdlib/src/erl_tar.erl
index d0e7a827a8..a383a0fc67 100644
--- a/lib/stdlib/src/erl_tar.erl
+++ b/lib/stdlib/src/erl_tar.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl
index fea1656051..665685d3ee 100644
--- a/lib/stdlib/src/error_logger_file_h.erl
+++ b/lib/stdlib/src/error_logger_file_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl
index d2df6681e3..cb22a8c0b6 100644
--- a/lib/stdlib/src/error_logger_tty_h.erl
+++ b/lib/stdlib/src/error_logger_tty_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl
index 1fca3624dc..3f74e01692 100644
--- a/lib/stdlib/src/ets.erl
+++ b/lib/stdlib/src/ets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl
index b3698fb3f5..80667023fb 100644
--- a/lib/stdlib/src/eval_bits.erl
+++ b/lib/stdlib/src/eval_bits.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl
index 51ffd1cff9..7029389e2f 100644
--- a/lib/stdlib/src/filelib.erl
+++ b/lib/stdlib/src/filelib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index 37f87b1ff9..c4586171ca 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/gen.erl b/lib/stdlib/src/gen.erl
index a05c2ce6fd..597830cf9a 100644
--- a/lib/stdlib/src/gen.erl
+++ b/lib/stdlib/src/gen.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -26,7 +26,8 @@
%%%
%%% The standard behaviour should export init_it/6.
%%%-----------------------------------------------------------------
--export([start/5, start/6, debug_options/1,
+-export([start/5, start/6, debug_options/2,
+ name/1, unregister_name/1, get_proc_name/1, get_parent/0,
call/3, call/4, reply/2, stop/1, stop/3]).
-export([init_it/6, init_it/7]).
@@ -124,7 +125,7 @@ init_it(GenMod, Starter, Parent, Mod, Args, Options) ->
init_it2(GenMod, Starter, Parent, self(), Mod, Args, Options).
init_it(GenMod, Starter, Parent, Name, Mod, Args, Options) ->
- case name_register(Name) of
+ case register_name(Name) of
true ->
init_it2(GenMod, Starter, Parent, Name, Mod, Args, Options);
{false, Pid} ->
@@ -297,19 +298,19 @@ where({global, Name}) -> global:whereis_name(Name);
where({via, Module, Name}) -> Module:whereis_name(Name);
where({local, Name}) -> whereis(Name).
-name_register({local, Name} = LN) ->
+register_name({local, Name} = LN) ->
try register(Name, self()) of
true -> true
catch
error:_ ->
{false, where(LN)}
end;
-name_register({global, Name} = GN) ->
+register_name({global, Name} = GN) ->
case global:register_name(Name, self()) of
yes -> true;
no -> {false, where(GN)}
end;
-name_register({via, Module, Name} = GN) ->
+register_name({via, Module, Name} = GN) ->
case Module:register_name(Name, self()) of
yes ->
true;
@@ -317,34 +318,108 @@ name_register({via, Module, Name} = GN) ->
{false, where(GN)}
end.
+name({local,Name}) -> Name;
+name({global,Name}) -> Name;
+name({via,_, Name}) -> Name;
+name(Pid) when is_pid(Pid) -> Pid.
+
+unregister_name({local,Name}) ->
+ try unregister(Name) of
+ _ -> ok
+ catch
+ _:_ -> ok
+ end;
+unregister_name({global,Name}) ->
+ _ = global:unregister_name(Name),
+ ok;
+unregister_name({via, Mod, Name}) ->
+ _ = Mod:unregister_name(Name),
+ ok;
+unregister_name(Pid) when is_pid(Pid) ->
+ ok.
+
+get_proc_name(Pid) when is_pid(Pid) ->
+ Pid;
+get_proc_name({local, Name}) ->
+ case process_info(self(), registered_name) of
+ {registered_name, Name} ->
+ Name;
+ {registered_name, _Name} ->
+ exit(process_not_registered);
+ [] ->
+ exit(process_not_registered)
+ end;
+get_proc_name({global, Name}) ->
+ case global:whereis_name(Name) of
+ undefined ->
+ exit(process_not_registered_globally);
+ Pid when Pid =:= self() ->
+ Name;
+ _Pid ->
+ exit(process_not_registered_globally)
+ end;
+get_proc_name({via, Mod, Name}) ->
+ case Mod:whereis_name(Name) of
+ undefined ->
+ exit({process_not_registered_via, Mod});
+ Pid when Pid =:= self() ->
+ Name;
+ _Pid ->
+ exit({process_not_registered_via, Mod})
+ end.
+
+get_parent() ->
+ case get('$ancestors') of
+ [Parent | _] when is_pid(Parent) ->
+ Parent;
+ [Parent | _] when is_atom(Parent) ->
+ name_to_pid(Parent);
+ _ ->
+ exit(process_was_not_started_by_proc_lib)
+ end.
+
+name_to_pid(Name) ->
+ case whereis(Name) of
+ undefined ->
+ case global:whereis_name(Name) of
+ undefined ->
+ exit(could_not_find_registered_name);
+ Pid ->
+ Pid
+ end;
+ Pid ->
+ Pid
+ end.
+
timeout(Options) ->
- case opt(timeout, Options) of
- {ok, Time} ->
+ case lists:keyfind(timeout, 1, Options) of
+ {_,Time} ->
Time;
- _ ->
+ false ->
infinity
end.
spawn_opts(Options) ->
- case opt(spawn_opt, Options) of
- {ok, Opts} ->
+ case lists:keyfind(spawn_opt, 1, Options) of
+ {_,Opts} ->
Opts;
- _ ->
+ false ->
[]
end.
-opt(Op, [{Op, Value}|_]) ->
- {ok, Value};
-opt(Op, [_|Options]) ->
- opt(Op, Options);
-opt(_, []) ->
- false.
-
-debug_options(Opts) ->
- case opt(debug, Opts) of
- {ok, Options} -> sys:debug_options(Options);
- _ -> []
+debug_options(Name, Opts) ->
+ case lists:keyfind(debug, 1, Opts) of
+ {_,Options} ->
+ try sys:debug_options(Options)
+ catch _:_ ->
+ error_logger:format(
+ "~p: ignoring erroneous debug options - ~p~n",
+ [Name,Options]),
+ []
+ end;
+ false ->
+ []
end.
format_status_header(TagLine, Pid) when is_pid(Pid) ->
diff --git a/lib/stdlib/src/gen_event.erl b/lib/stdlib/src/gen_event.erl
index 3d63c19de7..ccacf658e9 100644
--- a/lib/stdlib/src/gen_event.erl
+++ b/lib/stdlib/src/gen_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -147,16 +147,11 @@ init_it(Starter, self, Name, Mod, Args, Options) ->
init_it(Starter, self(), Name, Mod, Args, Options);
init_it(Starter, Parent, Name0, _, _, Options) ->
process_flag(trap_exit, true),
- Debug = gen:debug_options(Options),
+ Name = gen:name(Name0),
+ Debug = gen:debug_options(Name, Options),
proc_lib:init_ack(Starter, {ok, self()}),
- Name = name(Name0),
loop(Parent, Name, [], Debug, false).
-name({local,Name}) -> Name;
-name({global,Name}) -> Name;
-name({via,_, Name}) -> Name;
-name(Pid) when is_pid(Pid) -> Pid.
-
-spec add_handler(emgr_ref(), handler(), term()) -> term().
add_handler(M, Handler, Args) -> rpc(M, {add_handler, Handler, Args}).
diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl
index 7eabb95548..6e7528fd98 100644
--- a/lib/stdlib/src/gen_fsm.erl
+++ b/lib/stdlib/src/gen_fsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -305,64 +305,11 @@ enter_loop(Mod, Options, StateName, StateData, Timeout) ->
enter_loop(Mod, Options, StateName, StateData, self(), Timeout).
enter_loop(Mod, Options, StateName, StateData, ServerName, Timeout) ->
- Name = get_proc_name(ServerName),
- Parent = get_parent(),
- Debug = gen:debug_options(Options),
+ Name = gen:get_proc_name(ServerName),
+ Parent = gen:get_parent(),
+ Debug = gen:debug_options(Name, Options),
loop(Parent, Name, StateName, StateData, Mod, Timeout, Debug).
-get_proc_name(Pid) when is_pid(Pid) ->
- Pid;
-get_proc_name({local, Name}) ->
- case process_info(self(), registered_name) of
- {registered_name, Name} ->
- Name;
- {registered_name, _Name} ->
- exit(process_not_registered);
- [] ->
- exit(process_not_registered)
- end;
-get_proc_name({global, Name}) ->
- case global:whereis_name(Name) of
- undefined ->
- exit(process_not_registered_globally);
- Pid when Pid =:= self() ->
- Name;
- _Pid ->
- exit(process_not_registered_globally)
- end;
-get_proc_name({via, Mod, Name}) ->
- case Mod:whereis_name(Name) of
- undefined ->
- exit({process_not_registered_via, Mod});
- Pid when Pid =:= self() ->
- Name;
- _Pid ->
- exit({process_not_registered_via, Mod})
- end.
-
-get_parent() ->
- case get('$ancestors') of
- [Parent | _] when is_pid(Parent) ->
- Parent;
- [Parent | _] when is_atom(Parent) ->
- name_to_pid(Parent);
- _ ->
- exit(process_was_not_started_by_proc_lib)
- end.
-
-name_to_pid(Name) ->
- case whereis(Name) of
- undefined ->
- case global:whereis_name(Name) of
- undefined ->
- exit(could_not_find_registered_name);
- Pid ->
- Pid
- end;
- Pid ->
- Pid
- end.
-
%%% ---------------------------------------------------
%%% Initiate the new process.
%%% Register the name using the Rfunc function
@@ -373,8 +320,8 @@ name_to_pid(Name) ->
init_it(Starter, self, Name, Mod, Args, Options) ->
init_it(Starter, self(), Name, Mod, Args, Options);
init_it(Starter, Parent, Name0, Mod, Args, Options) ->
- Name = name(Name0),
- Debug = gen:debug_options(Options),
+ Name = gen:name(Name0),
+ Debug = gen:debug_options(Name, Options),
case catch Mod:init(Args) of
{ok, StateName, StateData} ->
proc_lib:init_ack(Starter, {ok, self()}),
@@ -383,15 +330,15 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
proc_lib:init_ack(Starter, {ok, self()}),
loop(Parent, Name, StateName, StateData, Mod, Timeout, Debug);
{stop, Reason} ->
- unregister_name(Name0),
+ gen:unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
ignore ->
- unregister_name(Name0),
+ gen:unregister_name(Name0),
proc_lib:init_ack(Starter, ignore),
exit(normal);
{'EXIT', Reason} ->
- unregister_name(Name0),
+ gen:unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
Else ->
@@ -400,20 +347,6 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
exit(Error)
end.
-name({local,Name}) -> Name;
-name({global,Name}) -> Name;
-name({via,_, Name}) -> Name;
-name(Pid) when is_pid(Pid) -> Pid.
-
-unregister_name({local,Name}) ->
- _ = (catch unregister(Name));
-unregister_name({global,Name}) ->
- _ = global:unregister_name(Name);
-unregister_name({via, Mod, Name}) ->
- _ = Mod:unregister_name(Name);
-unregister_name(Pid) when is_pid(Pid) ->
- Pid.
-
%%-----------------------------------------------------------------
%% The MAIN loop
%%-----------------------------------------------------------------
diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl
index c58b1de609..5800aca66f 100644
--- a/lib/stdlib/src/gen_server.erl
+++ b/lib/stdlib/src/gen_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -304,9 +304,9 @@ enter_loop(Mod, Options, State, Timeout) ->
enter_loop(Mod, Options, State, self(), Timeout).
enter_loop(Mod, Options, State, ServerName, Timeout) ->
- Name = get_proc_name(ServerName),
- Parent = get_parent(),
- Debug = debug_options(Name, Options),
+ Name = gen:get_proc_name(ServerName),
+ Parent = gen:get_parent(),
+ Debug = gen:debug_options(Name, Options),
loop(Parent, Name, State, Mod, Timeout, Debug).
%%%========================================================================
@@ -323,8 +323,8 @@ enter_loop(Mod, Options, State, ServerName, Timeout) ->
init_it(Starter, self, Name, Mod, Args, Options) ->
init_it(Starter, self(), Name, Mod, Args, Options);
init_it(Starter, Parent, Name0, Mod, Args, Options) ->
- Name = name(Name0),
- Debug = debug_options(Name, Options),
+ Name = gen:name(Name0),
+ Debug = gen:debug_options(Name, Options),
case catch Mod:init(Args) of
{ok, State} ->
proc_lib:init_ack(Starter, {ok, self()}),
@@ -339,15 +339,15 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
%% (Otherwise, the parent process could get
%% an 'already_started' error if it immediately
%% tried starting the process again.)
- unregister_name(Name0),
+ gen:unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
ignore ->
- unregister_name(Name0),
+ gen:unregister_name(Name0),
proc_lib:init_ack(Starter, ignore),
exit(normal);
{'EXIT', Reason} ->
- unregister_name(Name0),
+ gen:unregister_name(Name0),
proc_lib:init_ack(Starter, {error, Reason}),
exit(Reason);
Else ->
@@ -356,20 +356,6 @@ init_it(Starter, Parent, Name0, Mod, Args, Options) ->
exit(Error)
end.
-name({local,Name}) -> Name;
-name({global,Name}) -> Name;
-name({via,_, Name}) -> Name;
-name(Pid) when is_pid(Pid) -> Pid.
-
-unregister_name({local,Name}) ->
- _ = (catch unregister(Name));
-unregister_name({global,Name}) ->
- _ = global:unregister_name(Name);
-unregister_name({via, Mod, Name}) ->
- _ = Mod:unregister_name(Name);
-unregister_name(Pid) when is_pid(Pid) ->
- Pid.
-
%%%========================================================================
%%% Internal functions
%%%========================================================================
@@ -858,86 +844,6 @@ error_info(Reason, Name, Msg, State, Debug) ->
sys:print_log(Debug),
ok.
-%%% ---------------------------------------------------
-%%% Misc. functions.
-%%% ---------------------------------------------------
-
-opt(Op, [{Op, Value}|_]) ->
- {ok, Value};
-opt(Op, [_|Options]) ->
- opt(Op, Options);
-opt(_, []) ->
- false.
-
-debug_options(Name, Opts) ->
- case opt(debug, Opts) of
- {ok, Options} -> dbg_opts(Name, Options);
- _ -> []
- end.
-
-dbg_opts(Name, Opts) ->
- case catch sys:debug_options(Opts) of
- {'EXIT',_} ->
- format("~p: ignoring erroneous debug options - ~p~n",
- [Name, Opts]),
- [];
- Dbg ->
- Dbg
- end.
-
-get_proc_name(Pid) when is_pid(Pid) ->
- Pid;
-get_proc_name({local, Name}) ->
- case process_info(self(), registered_name) of
- {registered_name, Name} ->
- Name;
- {registered_name, _Name} ->
- exit(process_not_registered);
- [] ->
- exit(process_not_registered)
- end;
-get_proc_name({global, Name}) ->
- case global:whereis_name(Name) of
- undefined ->
- exit(process_not_registered_globally);
- Pid when Pid =:= self() ->
- Name;
- _Pid ->
- exit(process_not_registered_globally)
- end;
-get_proc_name({via, Mod, Name}) ->
- case Mod:whereis_name(Name) of
- undefined ->
- exit({process_not_registered_via, Mod});
- Pid when Pid =:= self() ->
- Name;
- _Pid ->
- exit({process_not_registered_via, Mod})
- end.
-
-get_parent() ->
- case get('$ancestors') of
- [Parent | _] when is_pid(Parent)->
- Parent;
- [Parent | _] when is_atom(Parent)->
- name_to_pid(Parent);
- _ ->
- exit(process_was_not_started_by_proc_lib)
- end.
-
-name_to_pid(Name) ->
- case whereis(Name) of
- undefined ->
- case global:whereis_name(Name) of
- undefined ->
- exit(could_not_find_registered_name);
- Pid ->
- Pid
- end;
- Pid ->
- Pid
- end.
-
%%-----------------------------------------------------------------
%% Status information
%%-----------------------------------------------------------------
diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl
new file mode 100644
index 0000000000..f9e2e5f7d2
--- /dev/null
+++ b/lib/stdlib/src/gen_statem.erl
@@ -0,0 +1,1267 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2016. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+-module(gen_statem).
+
+%% API
+-export(
+ [start/3,start/4,start_link/3,start_link/4,
+ stop/1,stop/3,
+ cast/2,call/2,call/3,
+ enter_loop/5,enter_loop/6,enter_loop/7,
+ reply/1,reply/2]).
+
+%% gen callbacks
+-export(
+ [init_it/6]).
+
+%% sys callbacks
+-export(
+ [system_continue/3,
+ system_terminate/4,
+ system_code_change/4,
+ system_get_state/1,
+ system_replace_state/2,
+ format_status/2]).
+
+%% Internal callbacks
+-export(
+ [wakeup_from_hibernate/3]).
+
+%% Type exports for templates
+-export_type(
+ [event_type/0,
+ callback_mode/0,
+ state_function_result/0,
+ handle_event_result/0,
+ action/0]).
+
+%% Fix problem for doc build
+-export_type([transition_option/0]).
+
+%%%==========================================================================
+%%% Interface functions.
+%%%==========================================================================
+
+-type from() ::
+ {To :: pid(), Tag :: term()}. % Reply-to specifier for call
+
+-type state() ::
+ state_name() | % For state callback function StateName/5
+ term(). % For state callback function handle_event/5
+
+-type state_name() :: atom().
+
+-type data() :: term().
+
+-type event_type() ::
+ {'call',From :: from()} | 'cast' |
+ 'info' | 'timeout' | 'internal'.
+
+-type callback_mode() :: 'state_functions' | 'handle_event_function'.
+
+-type transition_option() ::
+ postpone() | hibernate() | event_timeout().
+-type postpone() ::
+ %% If 'true' postpone the current event
+ %% and retry it when the state changes (=/=)
+ boolean().
+-type hibernate() ::
+ %% If 'true' hibernate the server instead of going into receive
+ boolean().
+-type event_timeout() ::
+ %% Generate a ('timeout', EventContent, ...) event after Time
+ %% unless some other event is delivered
+ Time :: timeout().
+
+-type action() ::
+ %% During a state change:
+ %% * NextState and NewData are set.
+ %% * All action()s are executed in order of apperance.
+ %% * Postponing the current event is performed
+ %% iff 'postpone' is 'true'.
+ %% * A state timer is started iff 'timeout' is set.
+ %% * Pending events are processed or if there are
+ %% no pending events the server goes into receive
+ %% or hibernate (iff 'hibernate' is 'true')
+ %%
+ %% These action()s are executed in order of appearence
+ %% in the containing list. The ones that set options
+ %% will override any previous so the last of each kind wins.
+ %%
+ 'postpone' | % Set the postpone option
+ {'postpone', Postpone :: postpone()} |
+ %%
+ 'hibernate' | % Set the hibernate option
+ {'hibernate', Hibernate :: hibernate()} |
+ %%
+ (Timeout :: event_timeout()) | % {timeout,Timeout}
+ {'timeout', % Set the event timeout option
+ Time :: event_timeout(), EventContent :: term()} |
+ %%
+ reply_action() |
+ %%
+ %% All 'next_event' events are kept in a list and then
+ %% inserted at state changes so the first in the
+ %% action() list is the first to be delivered.
+ {'next_event', % Insert event as the next to handle
+ EventType :: event_type(),
+ EventContent :: term()}.
+-type reply_action() ::
+ {'reply', % Reply to a caller
+ From :: from(), Reply :: term()}.
+
+-type state_function_result() ::
+ {'next_state', % {next_state,NextStateName,NewData,[]}
+ NextStateName :: state_name(),
+ NewData :: data()} |
+ {'next_state', % State transition, maybe to the same state
+ NextStateName :: state_name(),
+ NewData :: data(),
+ Actions :: [action()] | action()} |
+ common_state_callback_result().
+-type handle_event_result() ::
+ {'next_state', % {next_state,NextState,NewData,[]}
+ NextState :: state(),
+ NewData :: data()} |
+ {'next_state', % State transition, maybe to the same state
+ NextState :: state(),
+ NewData :: data(),
+ Actions :: [action()] | action()} |
+ common_state_callback_result().
+-type common_state_callback_result() ::
+ 'stop' | % {stop,normal}
+ {'stop', % Stop the server
+ Reason :: term()} |
+ {'stop', % Stop the server
+ Reason :: term(),
+ NewData :: data()} |
+ {'stop_and_reply', % Reply then stop the server
+ Reason :: term(),
+ Replies :: [reply_action()] | reply_action()} |
+ {'stop_and_reply', % Reply then stop the server
+ Reason :: term(),
+ Replies :: [reply_action()] | reply_action(),
+ NewData :: data()} |
+ {'keep_state', % {keep_state,NewData,[]}
+ NewData :: data()} |
+ {'keep_state', % Keep state, change data
+ NewData :: data(),
+ Actions :: [action()] | action()} |
+ 'keep_state_and_data' | % {keep_state_and_data,[]}
+ {'keep_state_and_data', % Keep state and data -> only actions
+ Actions :: [action()] | action()}.
+
+
+%% The state machine init function. It is called only once and
+%% the server is not running until this function has returned
+%% an {ok, ...} tuple. Thereafter the state callbacks are called
+%% for all events to this server.
+-callback init(Args :: term()) ->
+ {callback_mode(), state(), data()} |
+ {callback_mode(), state(), data(), [action()] | action()} |
+ 'ignore' |
+ {'stop', Reason :: term()}.
+
+%% Example state callback for callback_mode() =:= state_functions
+%% state name 'state_name'.
+%%
+%% In this mode all states has to be type state_name() i.e atom().
+%%
+%% Note that state callbacks and only state callbacks have arity 5
+%% and that is intended.
+-callback state_name(
+ event_type(),
+ EventContent :: term(),
+ Data :: data()) ->
+ state_function_result().
+%%
+%% State callback for callback_mode() =:= handle_event_function.
+%%
+%% Note that state callbacks and only state callbacks have arity 5
+%% and that is intended.
+-callback handle_event(
+ event_type(),
+ EventContent :: term(),
+ State :: state(), % Current state
+ Data :: data()) ->
+ handle_event_result().
+
+%% Clean up before the server terminates.
+-callback terminate(
+ Reason :: 'normal' | 'shutdown' | {'shutdown', term()}
+ | term(),
+ State :: state(),
+ Data :: data()) ->
+ any().
+
+%% Note that the new code can expect to get an OldState from
+%% the old code version not only in code_change/4 but in the first
+%% state callback function called thereafter
+-callback code_change(
+ OldVsn :: term() | {'down', term()},
+ OldState :: state(),
+ OldData :: data(),
+ Extra :: term()) ->
+ {NewCallbackMode :: callback_mode(),
+ NewState :: state(),
+ NewData :: data()}.
+
+%% Format the callback module state in some sensible that is
+%% often condensed way. For StatusOption =:= 'normal' the perferred
+%% return term is [{data,[{"State",FormattedState}]}], and for
+%% StatusOption =:= 'terminate' it is just FormattedState.
+-callback format_status(
+ StatusOption,
+ [ [{Key :: term(), Value :: term()}] |
+ state() |
+ data()]) ->
+ Status :: term() when
+ StatusOption :: 'normal' | 'terminate'.
+
+-optional_callbacks(
+ [init/1, % One may use enter_loop/5,6,7 instead
+ format_status/2, % Has got a default implementation
+ %%
+ state_name/3, % Example for callback_mode =:= state_functions:
+ %% there has to be a StateName/5 callback function for every StateName.
+ %%
+ handle_event/4]). % For callback_mode =:= handle_event_function
+
+%% Type validation functions
+callback_mode(CallbackMode) ->
+ case CallbackMode of
+ state_functions ->
+ true;
+ handle_event_function ->
+ true;
+ _ ->
+ false
+ end.
+%%
+from({Pid,_}) when is_pid(Pid) ->
+ true;
+from(_) ->
+ false.
+%%
+event_type({call,From}) ->
+ from(From);
+event_type(Type) ->
+ case Type of
+ cast ->
+ true;
+ info ->
+ true;
+ timeout ->
+ true;
+ internal ->
+ true;
+ _ ->
+ false
+ end.
+
+
+
+-define(
+ STACKTRACE(),
+ try throw(ok) catch _ -> erlang:get_stacktrace() end).
+
+-define(
+ TERMINATE(Class, Reason, Debug, S, Q),
+ terminate(
+ begin Class end,
+ begin Reason end,
+ ?STACKTRACE(),
+ begin Debug end,
+ begin S end,
+ begin Q end)).
+
+%%%==========================================================================
+%%% API
+
+-type server_name() ::
+ {'global', GlobalName :: term()}
+ | {'via', RegMod :: module(), Name :: term()}
+ | {'local', atom()}.
+-type server_ref() ::
+ {'global', GlobalName :: term()}
+ | {'via', RegMod :: module(), ViaName :: term()}
+ | (LocalName :: atom())
+ | {Name :: atom(), Node :: atom()}
+ | pid().
+-type debug_opt() ::
+ {'debug',
+ Dbgs ::
+ ['trace' | 'log' | 'statistics' | 'debug'
+ | {'logfile', string()}]}.
+-type start_opt() ::
+ debug_opt()
+ | {'timeout', Time :: timeout()}
+ | {'spawn_opt', [proc_lib:spawn_option()]}.
+-type start_ret() :: {'ok', pid()} | 'ignore' | {'error', term()}.
+
+
+
+%% Start a state machine
+-spec start(
+ Module :: module(), Args :: term(), Opts :: [start_opt()]) ->
+ start_ret().
+start(Module, Args, Opts) ->
+ gen:start(?MODULE, nolink, Module, Args, Opts).
+%%
+-spec start(
+ ServerName :: server_name(),
+ Module :: module(), Args :: term(), Opts :: [start_opt()]) ->
+ start_ret().
+start(ServerName, Module, Args, Opts) ->
+ gen:start(?MODULE, nolink, ServerName, Module, Args, Opts).
+
+%% Start and link to a state machine
+-spec start_link(
+ Module :: module(), Args :: term(), Opts :: [start_opt()]) ->
+ start_ret().
+start_link(Module, Args, Opts) ->
+ gen:start(?MODULE, link, Module, Args, Opts).
+%%
+-spec start_link(
+ ServerName :: server_name(),
+ Module :: module(), Args :: term(), Opts :: [start_opt()]) ->
+ start_ret().
+start_link(ServerName, Module, Args, Opts) ->
+ gen:start(?MODULE, link, ServerName, Module, Args, Opts).
+
+%% Stop a state machine
+-spec stop(ServerRef :: server_ref()) -> ok.
+stop(ServerRef) ->
+ gen:stop(ServerRef).
+%%
+-spec stop(
+ ServerRef :: server_ref(),
+ Reason :: term(),
+ Timeout :: timeout()) -> ok.
+stop(ServerRef, Reason, Timeout) ->
+ gen:stop(ServerRef, Reason, Timeout).
+
+%% Send an event to a state machine that arrives with type 'event'
+-spec cast(ServerRef :: server_ref(), Msg :: term()) -> ok.
+cast({global,Name}, Msg) ->
+ try global:send(Name, wrap_cast(Msg)) of
+ _ -> ok
+ catch
+ _:_ -> ok
+ end;
+cast({via,RegMod,Name}, Msg) ->
+ try RegMod:send(Name, wrap_cast(Msg)) of
+ _ -> ok
+ catch
+ _:_ -> ok
+ end;
+cast({Name,Node} = ServerRef, Msg) when is_atom(Name), is_atom(Node) ->
+ send(ServerRef, wrap_cast(Msg));
+cast(ServerRef, Msg) when is_atom(ServerRef) ->
+ send(ServerRef, wrap_cast(Msg));
+cast(ServerRef, Msg) when is_pid(ServerRef) ->
+ send(ServerRef, wrap_cast(Msg)).
+
+%% Call a state machine (synchronous; a reply is expected) that
+%% arrives with type {call,From}
+-spec call(ServerRef :: server_ref(), Request :: term()) -> Reply :: term().
+call(ServerRef, Request) ->
+ call(ServerRef, Request, infinity).
+%%
+-spec call(
+ ServerRef :: server_ref(),
+ Request :: term(),
+ Timeout :: timeout()) ->
+ Reply :: term().
+call(ServerRef, Request, infinity) ->
+ try gen:call(ServerRef, '$gen_call', Request, infinity) of
+ {ok,Reply} ->
+ Reply
+ catch
+ Class:Reason ->
+ erlang:raise(
+ Class,
+ {Reason,{?MODULE,call,[ServerRef,Request,infinity]}},
+ erlang:get_stacktrace())
+ end;
+call(ServerRef, Request, Timeout) ->
+ %% Call server through proxy process to dodge any late reply
+ Ref = make_ref(),
+ Self = self(),
+ Pid = spawn(
+ fun () ->
+ Self !
+ try gen:call(
+ ServerRef, '$gen_call', Request, Timeout) of
+ Result ->
+ {Ref,Result}
+ catch Class:Reason ->
+ {Ref,Class,Reason,erlang:get_stacktrace()}
+ end
+ end),
+ Mref = monitor(process, Pid),
+ receive
+ {Ref,Result} ->
+ demonitor(Mref, [flush]),
+ case Result of
+ {ok,Reply} ->
+ Reply
+ end;
+ {Ref,Class,Reason,Stacktrace} ->
+ demonitor(Mref, [flush]),
+ erlang:raise(
+ Class,
+ {Reason,{?MODULE,call,[ServerRef,Request,Timeout]}},
+ Stacktrace);
+ {'DOWN',Mref,_,_,Reason} ->
+ %% There is a theoretical possibility that the
+ %% proxy process gets killed between try--of and !
+ %% so this clause is in case of that
+ exit(Reason)
+ end.
+
+%% Reply from a state machine callback to whom awaits in call/2
+-spec reply([reply_action()] | reply_action()) -> ok.
+reply({reply,From,Reply}) ->
+ reply(From, Reply);
+reply(Replies) when is_list(Replies) ->
+ replies(Replies).
+%%
+-spec reply(From :: from(), Reply :: term()) -> ok.
+reply({To,Tag}, Reply) when is_pid(To) ->
+ Msg = {Tag,Reply},
+ try To ! Msg of
+ _ ->
+ ok
+ catch
+ _:_ -> ok
+ end.
+
+%% Instead of starting the state machine through start/3,4
+%% or start_link/3,4 turn the current process presumably
+%% started by proc_lib into a state machine using
+%% the same arguments as you would have returned from init/1
+-spec enter_loop(
+ Module :: module(), Opts :: [debug_opt()],
+ CallbackMode :: callback_mode(),
+ State :: state(), Data :: data()) ->
+ no_return().
+enter_loop(Module, Opts, CallbackMode, State, Data) ->
+ enter_loop(Module, Opts, CallbackMode, State, Data, self()).
+%%
+-spec enter_loop(
+ Module :: module(), Opts :: [debug_opt()],
+ CallbackMode :: callback_mode(),
+ State :: state(), Data :: data(),
+ Server_or_Actions ::
+ server_name() | pid() | [action()]) ->
+ no_return().
+enter_loop(Module, Opts, CallbackMode, State, Data, Server_or_Actions) ->
+ if
+ is_list(Server_or_Actions) ->
+ enter_loop(
+ Module, Opts, CallbackMode, State, Data,
+ self(), Server_or_Actions);
+ true ->
+ enter_loop(
+ Module, Opts, CallbackMode, State, Data,
+ Server_or_Actions, [])
+ end.
+%%
+-spec enter_loop(
+ Module :: module(), Opts :: [debug_opt()],
+ CallbackMode :: callback_mode(),
+ State :: state(), Data :: data(),
+ Server :: server_name() | pid(),
+ Actions :: [action()] | action()) ->
+ no_return().
+enter_loop(Module, Opts, CallbackMode, State, Data, Server, Actions) ->
+ is_atom(Module) orelse error({atom,Module}),
+ callback_mode(CallbackMode) orelse error({callback_mode,CallbackMode}),
+ Parent = gen:get_parent(),
+ enter(Module, Opts, CallbackMode, State, Data, Server, Actions, Parent).
+
+%%---------------------------------------------------------------------------
+%% API helpers
+
+wrap_cast(Event) ->
+ {'$gen_cast',Event}.
+
+replies([{reply,From,Reply}|Replies]) ->
+ reply(From, Reply),
+ replies(Replies);
+replies([]) ->
+ ok.
+
+%% Might actually not send the message in case of caught exception
+send(Proc, Msg) ->
+ try erlang:send(Proc, Msg, [noconnect]) of
+ noconnect ->
+ _ = spawn(erlang, send, [Proc,Msg]),
+ ok;
+ ok ->
+ ok
+ catch
+ _:_ ->
+ ok
+ end.
+
+%% Here init_it/6 and enter_loop/5,6,7 functions converge
+enter(Module, Opts, CallbackMode, State, Data, Server, Actions, Parent) ->
+ %% The values should already have been type checked
+ Name = gen:get_proc_name(Server),
+ Debug = gen:debug_options(Name, Opts),
+ PrevState = make_ref(), % Will be discarded by loop_event_actions/9
+ NewActions =
+ if
+ is_list(Actions) ->
+ Actions ++ [{postpone,false}];
+ true ->
+ [Actions,{postpone,false}]
+ end,
+ S = #{
+ callback_mode => CallbackMode,
+ module => Module,
+ name => Name,
+ state => PrevState,
+ data => Data,
+ timer => undefined,
+ postponed => [],
+ hibernate => false},
+ loop_event_actions(
+ Parent, Debug, S, [],
+ {event,undefined}, % Will be discarded thanks to {postpone,false}
+ PrevState, State, Data, NewActions).
+
+%%%==========================================================================
+%%% gen callbacks
+
+init_it(Starter, self, ServerRef, Module, Args, Opts) ->
+ init_it(Starter, self(), ServerRef, Module, Args, Opts);
+init_it(Starter, Parent, ServerRef, Module, Args, Opts) ->
+ try Module:init(Args) of
+ Result ->
+ init_result(Starter, Parent, ServerRef, Module, Result, Opts)
+ catch
+ Result ->
+ init_result(Starter, Parent, ServerRef, Module, Result, Opts);
+ Class:Reason ->
+ gen:unregister_name(ServerRef),
+ proc_lib:init_ack(Starter, {error,Reason}),
+ erlang:raise(Class, Reason, erlang:get_stacktrace())
+ end.
+
+%%---------------------------------------------------------------------------
+%% gen callbacks helpers
+
+init_result(Starter, Parent, ServerRef, Module, Result, Opts) ->
+ case Result of
+ {CallbackMode,State,Data} ->
+ case callback_mode(CallbackMode) of
+ true ->
+ proc_lib:init_ack(Starter, {ok,self()}),
+ enter(
+ Module, Opts, CallbackMode, State, Data,
+ ServerRef, [], Parent);
+ false ->
+ Error = {callback_mode,CallbackMode},
+ proc_lib:init_ack(Starter, {error,Error}),
+ exit(Error)
+ end;
+ {CallbackMode,State,Data,Actions} ->
+ case callback_mode(CallbackMode) of
+ true ->
+ proc_lib:init_ack(Starter, {ok,self()}),
+ enter(
+ Module, Opts, CallbackMode, State, Data,
+ ServerRef, Actions, Parent);
+ false ->
+ Error = {callback_mode,CallbackMode},
+ proc_lib:init_ack(Starter, {error,Error}),
+ exit(Error)
+ end;
+ {stop,Reason} ->
+ gen:unregister_name(ServerRef),
+ proc_lib:init_ack(Starter, {error,Reason}),
+ exit(Reason);
+ ignore ->
+ gen:unregister_name(ServerRef),
+ proc_lib:init_ack(Starter, ignore),
+ exit(normal);
+ _ ->
+ Error = {bad_return_value,Result},
+ proc_lib:init_ack(Starter, {error,Error}),
+ exit(Error)
+ end.
+
+%%%==========================================================================
+%%% sys callbacks
+
+system_continue(Parent, Debug, S) ->
+ loop(Parent, Debug, S).
+
+system_terminate(Reason, _Parent, Debug, S) ->
+ ?TERMINATE(exit, Reason, Debug, S, []).
+
+system_code_change(
+ #{module := Module,
+ state := State,
+ data := Data} = S,
+ _Mod, OldVsn, Extra) ->
+ case
+ try Module:code_change(OldVsn, State, Data, Extra)
+ catch
+ Result -> Result
+ end
+ of
+ {NewCallbackMode,NewState,NewData} ->
+ callback_mode(NewCallbackMode) orelse
+ error({callback_mode,NewCallbackMode}),
+ {ok,S#{state := NewState, data := NewData}};
+ {ok,_} = Error ->
+ error({case_clause,Error});
+ Error ->
+ Error
+ end.
+
+system_get_state(#{state := State, data := Data}) ->
+ {ok,{State,Data}}.
+
+system_replace_state(
+ StateFun,
+ #{state := State,
+ data := Data} = S) ->
+ {NewState,NewData} = Result = StateFun({State,Data}),
+ {ok,Result,S#{state := NewState, data := NewData}}.
+
+format_status(
+ Opt,
+ [PDict,SysState,Parent,Debug,
+ #{name := Name, postponed := P} = S]) ->
+ Header = gen:format_status_header("Status for state machine", Name),
+ Log = sys:get_debug(log, Debug, []),
+ [{header,Header},
+ {data,
+ [{"Status",SysState},
+ {"Parent",Parent},
+ {"Logged Events",Log},
+ {"Postponed",P}]} |
+ case format_status(Opt, PDict, S) of
+ L when is_list(L) -> L;
+ T -> [T]
+ end].
+
+%%---------------------------------------------------------------------------
+%% Format debug messages. Print them as the call-back module sees
+%% them, not as the real erlang messages. Use trace for that.
+%%---------------------------------------------------------------------------
+
+print_event(Dev, {in,Event}, #{name := Name}) ->
+ io:format(
+ Dev, "*DBG* ~p received ~s~n",
+ [Name,event_string(Event)]);
+print_event(Dev, {out,Reply,{To,_Tag}}, #{name := Name}) ->
+ io:format(
+ Dev, "*DBG* ~p sent ~p to ~p~n",
+ [Name,Reply,To]);
+print_event(Dev, {Tag,Event,NewState}, #{name := Name, state := State}) ->
+ StateString =
+ case NewState of
+ State ->
+ io_lib:format("~p", [State]);
+ _ ->
+ io_lib:format("~p => ~p", [State,NewState])
+ end,
+ io:format(
+ Dev, "*DBG* ~p ~w ~s in state ~s~n",
+ [Name,Tag,event_string(Event),StateString]).
+
+event_string(Event) ->
+ case Event of
+ {{call,{Pid,_Tag}},Request} ->
+ io_lib:format("call ~p from ~w", [Request,Pid]);
+ {Tag,Content} ->
+ io_lib:format("~w ~p", [Tag,Content])
+ end.
+
+sys_debug(Debug, S, Entry) ->
+ case Debug of
+ [] ->
+ Debug;
+ _ ->
+ sys:handle_debug(Debug, fun print_event/3, S, Entry)
+ end.
+
+%%%==========================================================================
+%%% Internal callbacks
+
+wakeup_from_hibernate(Parent, Debug, S) ->
+ %% It is a new message that woke us up so we have to receive it now
+ loop_receive(Parent, Debug, S).
+
+%%%==========================================================================
+%%% State Machine engine implementation of proc_lib/gen server
+
+%% Server loop, consists of all loop* functions
+%% and some detours through sys and proc_lib
+
+%% Entry point for system_continue/3
+loop(Parent, Debug, #{hibernate := Hibernate} = S) ->
+ case Hibernate of
+ true ->
+ %% Does not return but restarts process at
+ %% wakeup_from_hibernate/3 that jumps to loop_receive/3
+ proc_lib:hibernate(
+ ?MODULE, wakeup_from_hibernate, [Parent,Debug,S]),
+ error(
+ {should_not_have_arrived_here_but_instead_in,
+ {wakeup_from_hibernate,3}});
+ false ->
+ loop_receive(Parent, Debug, S)
+ end.
+
+%% Entry point for wakeup_from_hibernate/3
+loop_receive(Parent, Debug, #{timer := Timer} = S) ->
+ receive
+ Msg ->
+ case Msg of
+ {system,Pid,Req} ->
+ #{hibernate := Hibernate} = S,
+ %% Does not return but tail recursively calls
+ %% system_continue/3 that jumps to loop/3
+ sys:handle_system_msg(
+ Req, Pid, Parent, ?MODULE, Debug, S, Hibernate);
+ {'EXIT',Parent,Reason} = EXIT ->
+ %% EXIT is not a 2-tuple and therefore
+ %% not an event and has no event_type(),
+ %% but this will stand out in the crash report...
+ ?TERMINATE(exit, Reason, Debug, S, [EXIT]);
+ {timeout,Timer,Content} when Timer =/= undefined ->
+ loop_event(Parent, Debug, S, {timeout,Content});
+ _ ->
+ %% Cancel Timer if running
+ case Timer of
+ undefined ->
+ ok;
+ _ ->
+ case erlang:cancel_timer(Timer) of
+ TimeLeft when is_integer(TimeLeft) ->
+ ok;
+ false ->
+ receive
+ {timeout,Timer,_} ->
+ ok
+ after 0 ->
+ ok
+ end
+ end
+ end,
+ Event =
+ case Msg of
+ {'$gen_call',From,Request} ->
+ {{call,From},Request};
+ {'$gen_cast',E} ->
+ {cast,E};
+ _ ->
+ {info,Msg}
+ end,
+ loop_event(Parent, Debug, S, Event)
+ end
+ end.
+
+loop_event(Parent, Debug, S, Event) ->
+ %% The timer field and the hibernate flag in S
+ %% are now invalid and ignored until we get back to loop/3
+ NewDebug = sys_debug(Debug, S, {in,Event}),
+ %% Here the queue of not yet processed events is created
+ loop_events(Parent, NewDebug, S, [Event], false).
+
+%% Process first the event queue, or if it is empty
+%% loop back to receive a new event
+loop_events(Parent, Debug, S, [], _Hibernate) ->
+ loop(Parent, Debug, S);
+loop_events(
+ Parent, Debug,
+ #{callback_mode := CallbackMode,
+ module := Module,
+ state := State,
+ data := Data} = S,
+ [{Type,Content} = Event|Events] = Q,
+ Hibernate) ->
+ %% If the Hibernate flag is true here it can only be
+ %% because it was set from an event action
+ %% and we did not go into hibernation since there
+ %% were events in queue, so we do what the user
+ %% might depend on i.e collect garbage which
+ %% would have happened if we actually hibernated
+ %% and immediately was awakened
+ Hibernate andalso garbage_collect(),
+ try
+ case CallbackMode of
+ state_functions ->
+ Module:State(Type, Content, Data);
+ handle_event_function ->
+ Module:handle_event(Type, Content, State, Data)
+ end of
+ Result ->
+ loop_event_result(
+ Parent, Debug, S, Events, Event, Result)
+ catch
+ Result ->
+ loop_event_result(
+ Parent, Debug, S, Events, Event, Result);
+ error:badarg when CallbackMode =:= state_functions ->
+ case erlang:get_stacktrace() of
+ [{erlang,apply,[Module,State,_],_}|Stacktrace] ->
+ Args = [Type,Content,Data],
+ terminate(
+ error,
+ {undef_state_function,{Module,State,Args}},
+ Stacktrace,
+ Debug, S, Q);
+ Stacktrace ->
+ terminate(error, badarg, Stacktrace, Debug, S, Q)
+ end;
+ error:undef ->
+ %% Process an undef to check for the simple mistake
+ %% of calling a nonexistent state function
+ case erlang:get_stacktrace() of
+ [{Module,State,
+ [Type,Content,Data]=Args,
+ _}
+ |Stacktrace]
+ when CallbackMode =:= state_functions ->
+ terminate(
+ error,
+ {undef_state_function,{Module,State,Args}},
+ Stacktrace,
+ Debug, S, Q);
+ [{Module,handle_event,
+ [Type,Content,State,Data]=Args,
+ _}
+ |Stacktrace]
+ when CallbackMode =:= handle_event_function ->
+ terminate(
+ error,
+ {undef_state_function,
+ {Module,handle_event,Args}},
+ Stacktrace,
+ Debug, S, Q);
+ Stacktrace ->
+ terminate(error, undef, Stacktrace, Debug, S, Q)
+ end;
+ Class:Reason ->
+ Stacktrace = erlang:get_stacktrace(),
+ terminate(Class, Reason, Stacktrace, Debug, S, Q)
+ end.
+
+%% Interpret all callback return variants
+loop_event_result(
+ Parent, Debug,
+ #{state := State, data := Data} = S,
+ Events, Event, Result) ->
+ %% From now until we loop back to the loop_events/4
+ %% the state and data fields in S are old
+ case Result of
+ stop ->
+ ?TERMINATE(exit, normal, Debug, S, [Event|Events]);
+ {stop,Reason} ->
+ ?TERMINATE(exit, Reason, Debug, S, [Event|Events]);
+ {stop,Reason,NewData} ->
+ NewS = S#{data := NewData},
+ Q = [Event|Events],
+ ?TERMINATE(exit, Reason, Debug, NewS, Q);
+ {stop_and_reply,Reason,Replies} ->
+ Q = [Event|Events],
+ [Class,NewReason,Stacktrace,NewDebug] =
+ reply_then_terminate(
+ exit, Reason, ?STACKTRACE(), Debug, S, Q, Replies),
+ %% Since we got back here Replies was bad
+ terminate(Class, NewReason, Stacktrace, NewDebug, S, Q);
+ {stop_and_reply,Reason,Replies,NewData} ->
+ NewS = S#{data := NewData},
+ Q = [Event|Events],
+ [Class,NewReason,Stacktrace,NewDebug] =
+ reply_then_terminate(
+ exit, Reason, ?STACKTRACE(), Debug, NewS, Q, Replies),
+ %% Since we got back here Replies was bad
+ terminate(Class, NewReason, Stacktrace, NewDebug, NewS, Q);
+ {next_state,NextState,NewData} ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, []);
+ {next_state,NextState,NewData,Actions} ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions);
+ {keep_state,NewData} ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, State, NewData, []);
+ {keep_state,NewData,Actions} ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, State, NewData, Actions);
+ keep_state_and_data ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, State, Data, []);
+ {keep_state_and_data,Actions} ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, State, Data, Actions);
+ _ ->
+ ?TERMINATE(
+ error, {bad_return_value,Result}, Debug, S, [Event|Events])
+ end.
+
+loop_event_actions(
+ Parent, Debug, S, Events, Event, State, NextState, NewData, Actions) ->
+ Postpone = false, % Shall we postpone this event, true or false
+ Hibernate = false,
+ Timeout = undefined,
+ NextEvents = [],
+ loop_event_actions(
+ Parent, Debug, S, Events, Event, State, NextState, NewData,
+ if
+ is_list(Actions) ->
+ Actions;
+ true ->
+ [Actions]
+ end,
+ Postpone, Hibernate, Timeout, NextEvents).
+%%
+%% Process all action()s
+loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, [Action|Actions],
+ Postpone, Hibernate, Timeout, NextEvents) ->
+ case Action of
+ %% Actual actions
+ {reply,From,Reply} ->
+ case from(From) of
+ true ->
+ NewDebug = do_reply(Debug, S, From, Reply),
+ loop_event_actions(
+ Parent, NewDebug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ Postpone, Hibernate, Timeout, NextEvents);
+ false ->
+ ?TERMINATE(
+ error, {bad_action,Action}, Debug, S, [Event|Events])
+ end;
+ {next_event,Type,Content} ->
+ case event_type(Type) of
+ true ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ Postpone, Hibernate, Timeout,
+ [{Type,Content}|NextEvents]);
+ false ->
+ ?TERMINATE(
+ error, {bad_action,Action}, Debug, S, [Event|Events])
+ end;
+ %% Actions that set options
+ {postpone,NewPostpone} when is_boolean(NewPostpone) ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ NewPostpone, Hibernate, Timeout, NextEvents);
+ {postpone,_} ->
+ ?TERMINATE(
+ error, {bad_action,Action}, Debug, S, [Event|Events]);
+ postpone ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ true, Hibernate, Timeout, NextEvents);
+ {hibernate,NewHibernate} when is_boolean(NewHibernate) ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ Postpone, NewHibernate, Timeout, NextEvents);
+ {hibernate,_} ->
+ ?TERMINATE(
+ error, {bad_action,Action}, Debug, S, [Event|Events]);
+ hibernate ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ Postpone, true, Timeout, NextEvents);
+ {timeout,infinity,_} -> % Clear timer - it will never trigger
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ Postpone, Hibernate, undefined, NextEvents);
+ {timeout,Time,_} = NewTimeout when is_integer(Time), Time >= 0 ->
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ Postpone, Hibernate, NewTimeout, NextEvents);
+ {timeout,_,_} ->
+ ?TERMINATE(
+ error, {bad_action,Action}, Debug, S, [Event|Events]);
+ infinity -> % Clear timer - it will never trigger
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ Postpone, Hibernate, undefined, NextEvents);
+ Time when is_integer(Time), Time >= 0 ->
+ NewTimeout = {timeout,Time,Time},
+ loop_event_actions(
+ Parent, Debug, S, Events, Event,
+ State, NextState, NewData, Actions,
+ Postpone, Hibernate, NewTimeout, NextEvents);
+ _ ->
+ ?TERMINATE(
+ error, {bad_action,Action}, Debug, S, [Event|Events])
+ end;
+%%
+%% End of actions list
+loop_event_actions(
+ Parent, Debug, #{postponed := P0} = S, Events, Event,
+ State, NextState, NewData, [],
+ Postpone, Hibernate, Timeout, NextEvents) ->
+ %%
+ %% All options have been collected and next_events are buffered.
+ %% Do the actual state transition.
+ %%
+ P1 = % Move current event to postponed if Postpone
+ case Postpone of
+ true ->
+ [Event|P0];
+ false ->
+ P0
+ end,
+ {Q2,P} = % Move all postponed events to queue if state change
+ if
+ NextState =:= State ->
+ {Events,P1};
+ true ->
+ {lists:reverse(P1, Events),[]}
+ end,
+ %% Place next events first in queue
+ Q3 = lists:reverse(NextEvents, Q2),
+ %%
+ NewDebug =
+ sys_debug(
+ Debug, S,
+ case Postpone of
+ true ->
+ {postpone,Event,NextState};
+ false ->
+ {consume,Event,NextState}
+ end),
+ %% Have a peek on the event queue so we can avoid starting
+ %% the state timer unless we have to
+ {Q,Timer} =
+ case Timeout of
+ undefined ->
+ %% No state timeout has been requested
+ {Q3,undefined};
+ {timeout,Time,EventContent} ->
+ %% A state timeout has been requested
+ case Q3 of
+ [] when Time =:= 0 ->
+ %% Immediate timeout - simulate it
+ %% so we do not get the timeout message
+ %% after any received event
+ {[{timeout,EventContent}],undefined};
+ [] ->
+ %% Actually start a timer
+ {Q3,erlang:start_timer(Time, self(), EventContent)};
+ _ ->
+ %% Do not start a timer since any queued
+ %% event cancels the state timer so we pretend
+ %% that the timer has been started and cancelled
+ {Q3,undefined}
+ end
+ end,
+ %% Loop to top of event queue loop; process next event
+ loop_events(
+ Parent, NewDebug,
+ S#{
+ state := NextState,
+ data := NewData,
+ timer := Timer,
+ postponed := P,
+ hibernate := Hibernate},
+ Q, Hibernate).
+
+%%---------------------------------------------------------------------------
+%% Server helpers
+
+reply_then_terminate(Class, Reason, Stacktrace, Debug, S, Q, Replies) ->
+ if
+ is_list(Replies) ->
+ do_reply_then_terminate(
+ Class, Reason, Stacktrace, Debug, S, Q, Replies);
+ true ->
+ do_reply_then_terminate(
+ Class, Reason, Stacktrace, Debug, S, Q, [Replies])
+ end.
+%%
+do_reply_then_terminate(Class, Reason, Stacktrace, Debug, S, Q, []) ->
+ terminate(Class, Reason, Stacktrace, Debug, S, Q);
+do_reply_then_terminate(
+ Class, Reason, Stacktrace, Debug, S, Q, [R|Rs]) ->
+ case R of
+ {reply,{_To,_Tag}=From,Reply} ->
+ NewDebug = do_reply(Debug, S, From, Reply),
+ do_reply_then_terminate(
+ Class, Reason, Stacktrace, NewDebug, S, Q, Rs);
+ _ ->
+ [error,{bad_action,R},?STACKTRACE(),Debug]
+ end.
+
+do_reply(Debug, S, From, Reply) ->
+ reply(From, Reply),
+ sys_debug(Debug, S, {out,Reply,From}).
+
+
+terminate(
+ Class, Reason, Stacktrace, Debug,
+ #{module := Module,
+ state := State, data := Data} = S,
+ Q) ->
+ try Module:terminate(Reason, State, Data) of
+ _ -> ok
+ catch
+ _ -> ok;
+ C:R ->
+ ST = erlang:get_stacktrace(),
+ error_info(
+ C, R, ST, Debug, S, Q,
+ format_status(terminate, get(), S)),
+ erlang:raise(C, R, ST)
+ end,
+ case Reason of
+ normal -> ok;
+ shutdown -> ok;
+ {shutdown,_} -> ok;
+ _ ->
+ error_info(
+ Class, Reason, Stacktrace, Debug, S, Q,
+ format_status(terminate, get(), S))
+ end,
+ case Stacktrace of
+ [] ->
+ erlang:Class(Reason);
+ _ ->
+ erlang:raise(Class, Reason, Stacktrace)
+ end.
+
+error_info(
+ Class, Reason, Stacktrace, Debug,
+ #{name := Name, callback_mode := CallbackMode,
+ state := State, postponed := P},
+ Q, FmtData) ->
+ {FixedReason,FixedStacktrace} =
+ case Stacktrace of
+ [{M,F,Args,_}|ST]
+ when Class =:= error, Reason =:= undef ->
+ case code:is_loaded(M) of
+ false ->
+ {{'module could not be loaded',M},ST};
+ _ ->
+ Arity =
+ if
+ is_list(Args) ->
+ length(Args);
+ is_integer(Args) ->
+ Args
+ end,
+ case erlang:function_exported(M, F, Arity) of
+ true ->
+ {Reason,Stacktrace};
+ false ->
+ {{'function not exported',{M,F,Arity}},
+ ST}
+ end
+ end;
+ _ -> {Reason,Stacktrace}
+ end,
+ error_logger:format(
+ "** State machine ~p terminating~n" ++
+ case Q of
+ [] ->
+ "";
+ _ ->
+ "** Last event = ~p~n"
+ end ++
+ "** When Server state = ~p~n" ++
+ "** Reason for termination = ~w:~p~n" ++
+ "** State = ~p~n" ++
+ "** Callback mode = ~p~n" ++
+ "** Queued/Postponed = ~w/~w~n" ++
+ case FixedStacktrace of
+ [] ->
+ "";
+ _ ->
+ "** Stacktrace =~n"
+ "** ~p~n"
+ end,
+ [Name |
+ case Q of
+ [] ->
+ [];
+ [Event|_] ->
+ [Event]
+ end] ++
+ [FmtData,Class,FixedReason,
+ State,CallbackMode,length(Q),length(P)] ++
+ case FixedStacktrace of
+ [] ->
+ [];
+ _ ->
+ [FixedStacktrace]
+ end),
+ sys:print_log(Debug),
+ ok.
+
+
+%% Call Module:format_status/2 or return a default value
+format_status(
+ Opt, PDict,
+ #{module := Module, state := State, data := Data}) ->
+ case erlang:function_exported(Module, format_status, 2) of
+ true ->
+ try Module:format_status(Opt, [PDict,State,Data])
+ catch
+ Result -> Result;
+ _:_ ->
+ format_status_default(
+ Opt, State,
+ "Module:format_status/2 crashed")
+ end;
+ false ->
+ format_status_default(Opt, State, Data)
+ end.
+
+%% The default Module:format_status/2
+format_status_default(Opt, State, Data) ->
+ SSD = {State,Data},
+ case Opt of
+ terminate ->
+ SSD;
+ _ ->
+ [{data,[{"State",SSD}]}]
+ end.
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index ef30f16f18..ad98bc0420 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -112,14 +112,14 @@
-type format_spec() ::
#{
- control_char => char(),
- args => [any()],
- width => 'none' | integer(),
- adjust => 'left' | 'right',
- precision => 'none' | integer(),
- pad_char => char(),
- encoding => 'unicode' | 'latin1',
- strings => boolean()
+ control_char := char(),
+ args := [any()],
+ width := 'none' | integer(),
+ adjust := 'left' | 'right',
+ precision := 'none' | integer(),
+ pad_char := char(),
+ encoding := 'unicode' | 'latin1',
+ strings := boolean()
}.
%%----------------------------------------------------------------------
diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl
index 282005da7d..1da866dc88 100644
--- a/lib/stdlib/src/io_lib_format.erl
+++ b/lib/stdlib/src/io_lib_format.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/io_lib_fread.erl b/lib/stdlib/src/io_lib_fread.erl
index 25555c6f52..6a8f8f728e 100644
--- a/lib/stdlib/src/io_lib_fread.erl
+++ b/lib/stdlib/src/io_lib_fread.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/io_lib_pretty.erl b/lib/stdlib/src/io_lib_pretty.erl
index 6309addf57..16ca2f41dc 100644
--- a/lib/stdlib/src/io_lib_pretty.erl
+++ b/lib/stdlib/src/io_lib_pretty.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/lib.erl b/lib/stdlib/src/lib.erl
index eb24516c50..6fba63a895 100644
--- a/lib/stdlib/src/lib.erl
+++ b/lib/stdlib/src/lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index 2b4472cdf7..af9d63ddd6 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -39,7 +39,8 @@
-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,
partition/2,zf/2,filtermap/2,
mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2,
- split/2]).
+ split/2,
+ join/2]).
%%% BIFs
-export([keyfind/3, keymember/3, keysearch/3, member/2, reverse/2]).
@@ -1439,6 +1440,18 @@ split(N, [H|T], R) ->
split(_, [], _) ->
badarg.
+-spec join(Sep, List1) -> List2 when
+ Sep :: T,
+ List1 :: [T],
+ List2 :: [T],
+ T :: term().
+
+join(_Sep, []) -> [];
+join(Sep, [H|T]) -> [H|join_prepend(Sep, T)].
+
+join_prepend(_Sep, []) -> [];
+join_prepend(Sep, [H|T]) -> [Sep,H|join_prepend(Sep,T)].
+
%%% =================================================================
%%% Here follows the implementation of the sort functions.
%%%
diff --git a/lib/stdlib/src/log_mf_h.erl b/lib/stdlib/src/log_mf_h.erl
index 35723bbc9e..393da9ab27 100644
--- a/lib/stdlib/src/log_mf_h.erl
+++ b/lib/stdlib/src/log_mf_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/maps.erl b/lib/stdlib/src/maps.erl
index 43d10f4800..5dafdb282a 100644
--- a/lib/stdlib/src/maps.erl
+++ b/lib/stdlib/src/maps.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,17 +20,18 @@
-module(maps).
--export([get/3,filter/2,fold/3, map/2,
- size/1,
+-export([get/3, filter/2,fold/3,
+ map/2, size/1,
+ update_with/3, update_with/4,
without/2, with/2]).
-
-%%% BIFs
+%% BIFs
-export([get/2, find/2, from_list/1,
is_key/2, keys/1, merge/2,
- new/0, put/3, remove/2,
+ new/0, put/3, remove/2, take/2,
to_list/1, update/3, values/1]).
+%% Shadowed by erl_bif_types: maps:get/2
-spec get(Key,Map) -> Value when
Key :: term(),
Map :: map(),
@@ -46,7 +47,7 @@ get(_,_) -> erlang:nif_error(undef).
find(_,_) -> erlang:nif_error(undef).
-
+%% Shadowed by erl_bif_types: maps:from_list/1
-spec from_list(List) -> Map when
List :: [{Key,Value}],
Key :: term(),
@@ -56,6 +57,7 @@ find(_,_) -> erlang:nif_error(undef).
from_list(_) -> erlang:nif_error(undef).
+%% Shadowed by erl_bif_types: maps:is_key/2
-spec is_key(Key,Map) -> boolean() when
Key :: term(),
Map :: map().
@@ -71,6 +73,7 @@ is_key(_,_) -> erlang:nif_error(undef).
keys(_) -> erlang:nif_error(undef).
+%% Shadowed by erl_bif_types: maps:merge/2
-spec merge(Map1,Map2) -> Map3 when
Map1 :: map(),
Map2 :: map(),
@@ -86,6 +89,7 @@ merge(_,_) -> erlang:nif_error(undef).
new() -> erlang:nif_error(undef).
+%% Shadowed by erl_bif_types: maps:put/3
-spec put(Key,Value,Map1) -> Map2 when
Key :: term(),
Value :: term(),
@@ -102,7 +106,15 @@ put(_,_,_) -> erlang:nif_error(undef).
remove(_,_) -> erlang:nif_error(undef).
+-spec take(Key,Map1) -> {Value,Map2} | error when
+ Key :: term(),
+ Map1 :: map(),
+ Value :: term(),
+ Map2 :: map().
+
+take(_,_) -> erlang:nif_error(undef).
+%% Shadowed by erl_bif_types: maps:to_list/1
-spec to_list(Map) -> [{Key,Value}] when
Map :: map(),
Key :: term(),
@@ -111,6 +123,7 @@ remove(_,_) -> erlang:nif_error(undef).
to_list(_) -> erlang:nif_error(undef).
+%% Shadowed by erl_bif_types: maps:update/3
-spec update(Key,Value,Map1) -> Map2 when
Key :: term(),
Value :: term(),
@@ -127,8 +140,40 @@ update(_,_,_) -> erlang:nif_error(undef).
values(_) -> erlang:nif_error(undef).
+%% End of BIFs
+
+-spec update_with(Key,Fun,Map1) -> Map2 when
+ Key :: term(),
+ Map1 :: map(),
+ Map2 :: map(),
+ Fun :: fun((Value1 :: term()) -> Value2 :: term()).
+
+update_with(Key,Fun,Map) when is_function(Fun,1), is_map(Map) ->
+ try maps:get(Key,Map) of
+ Val -> maps:update(Key,Fun(Val),Map)
+ catch
+ error:{badkey,_} ->
+ erlang:error({badkey,Key},[Key,Fun,Map])
+ end;
+update_with(Key,Fun,Map) ->
+ erlang:error(error_type(Map),[Key,Fun,Map]).
+
+
+-spec update_with(Key,Fun,Init,Map1) -> Map2 when
+ Key :: term(),
+ Map1 :: Map1,
+ Map2 :: Map2,
+ Fun :: fun((Value1 :: term()) -> Value2 :: term()),
+ Init :: term().
+
+update_with(Key,Fun,Init,Map) when is_function(Fun,1), is_map(Map) ->
+ case maps:find(Key,Map) of
+ {ok,Val} -> maps:update(Key,Fun(Val),Map);
+ error -> maps:put(Key,Init,Map)
+ end;
+update_with(Key,Fun,Init,Map) ->
+ erlang:error(error_type(Map),[Key,Fun,Init,Map]).
-%%% End of BIFs
-spec get(Key, Map, Default) -> Value | Default when
Key :: term(),
diff --git a/lib/stdlib/src/math.erl b/lib/stdlib/src/math.erl
index 06dfc01bbb..97c965e27a 100644
--- a/lib/stdlib/src/math.erl
+++ b/lib/stdlib/src/math.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/ordsets.erl b/lib/stdlib/src/ordsets.erl
index 6010b41006..569407f5ef 100644
--- a/lib/stdlib/src/ordsets.erl
+++ b/lib/stdlib/src/ordsets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 6f546da7b8..7a59523f06 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -47,18 +47,6 @@ obsolete(Module, Name, Arity) ->
obsolete_1(net, _, _) ->
{deprecated, "module 'net' obsolete; use 'net_adm'"};
-obsolete_1(erl_internal, builtins, 0) ->
- {deprecated, {erl_internal, bif, 2}};
-
-obsolete_1(erl_eval, seq, 2) ->
- {deprecated, {erl_eval, exprs, 2}};
-obsolete_1(erl_eval, seq, 3) ->
- {deprecated, {erl_eval, exprs, 3}};
-obsolete_1(erl_eval, arg_list, 2) ->
- {deprecated, {erl_eval, expr_list, 2}};
-obsolete_1(erl_eval, arg_list, 3) ->
- {deprecated, {erl_eval, expr_list, 3}};
-
obsolete_1(erlang, hash, 2) ->
{deprecated, {erlang, phash2, 2}};
@@ -70,11 +58,12 @@ obsolete_1(erlang, now, 0) ->
obsolete_1(calendar, local_time_to_universal_time, 1) ->
{deprecated, {calendar, local_time_to_universal_time_dst, 1}};
-obsolete_1(rpc, safe_multi_server_call, A) when A =:= 2; A =:= 3 ->
- {deprecated, {rpc, multi_server_call, A}};
+%% *** CRYPTO added in OTP 19 ***
+obsolete_1(crypto, rand_bytes, 1) ->
+ {deprecated, {crypto, strong_rand_bytes, 1}};
-%% *** CRYPTO add in R16B01 ***
+%% *** CRYPTO added in R16B01 ***
obsolete_1(crypto, md4, 1) ->
{deprecated, {crypto, hash, 2}};
@@ -391,106 +380,10 @@ obsolete_1(http, cookie_header, 2) -> {removed,{httpc,cookie_header,2},"R15B"
obsolete_1(http, stream_next, 1) -> {removed,{httpc,stream_next,1},"R15B"};
obsolete_1(http, default_profile, 0) -> {removed,{httpc,default_profile,0},"R15B"};
-obsolete_1(httpd, start, 0) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start, 1) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start_link, 0) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start_link, 1) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start_child, 0) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start_child, 1) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, stop, 0) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop, 1) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop, 2) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop_child, 0) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop_child, 1) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop_child, 2) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, restart, 0) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, restart, 1) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, restart, 2) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 0) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 1) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 2) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 3) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 4) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, unblock, 0) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, unblock, 1) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, unblock, 2) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd_util, key1search, 2) -> {removed,{proplists,get_value,2},"R13B"};
-obsolete_1(httpd_util, key1search, 3) -> {removed,{proplists,get_value,3},"R13B"};
-obsolete_1(ftp, open, 3) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(ftp, force_active, 1) -> {removed,{inets,start,[2,3]},"R14B"};
-
-%% Added in R12B-4.
-obsolete_1(ssh_cm, connect, A) when 1 =< A, A =< 3 ->
- {removed,{ssh,connect,A},"R14B"};
-obsolete_1(ssh_cm, listen, A) when 2 =< A, A =< 4 ->
- {removed,{ssh,daemon,A},"R14B"};
-obsolete_1(ssh_cm, stop_listener, 1) ->
- {removed,{ssh,stop_listener,[1,2]},"R14B"};
-obsolete_1(ssh_cm, session_open, A) when A =:= 2; A =:= 4 ->
- {removed,{ssh_connection,session_channel,A},"R14B"};
-obsolete_1(ssh_cm, direct_tcpip, A) when A =:= 6; A =:= 8 ->
- {removed,{ssh_connection,direct_tcpip,A},"R14B"};
-obsolete_1(ssh_cm, tcpip_forward, 3) ->
- {removed,{ssh_connection,tcpip_forward,3},"R14B"};
-obsolete_1(ssh_cm, cancel_tcpip_forward, 3) ->
- {removed,{ssh_connection,cancel_tcpip_forward,3},"R14B"};
-obsolete_1(ssh_cm, open_pty, A) when A =:= 3; A =:= 7; A =:= 9 ->
- {removed,{ssh_connection,open_pty,A},"R14B"};
-obsolete_1(ssh_cm, setenv, 5) ->
- {removed,{ssh_connection,setenv,5},"R14B"};
-obsolete_1(ssh_cm, shell, 2) ->
- {removed,{ssh_connection,shell,2},"R14B"};
-obsolete_1(ssh_cm, exec, 4) ->
- {removed,{ssh_connection,exec,4},"R14B"};
-obsolete_1(ssh_cm, subsystem, 4) ->
- {removed,{ssh_connection,subsystem,4},"R14B"};
-obsolete_1(ssh_cm, winch, A) when A =:= 4; A =:= 6 ->
- {removed,{ssh_connection,window_change,A},"R14B"};
-obsolete_1(ssh_cm, signal, 3) ->
- {removed,{ssh_connection,signal,3},"R14B"};
-obsolete_1(ssh_cm, attach, A) when A =:= 2; A =:= 3 ->
- {removed,"no longer useful; removed in R14B"};
-obsolete_1(ssh_cm, detach, 2) ->
- {removed,"no longer useful; removed in R14B"};
-obsolete_1(ssh_cm, set_user_ack, 4) ->
- {removed,"no longer useful; removed in R14B"};
-obsolete_1(ssh_cm, adjust_window, 3) ->
- {removed,{ssh_connection,adjust_window,3},"R14B"};
-obsolete_1(ssh_cm, close, 2) ->
- {removed,{ssh_connection,close,2},"R14B"};
-obsolete_1(ssh_cm, stop, 1) ->
- {removed,{ssh,close,1},"R14B"};
-obsolete_1(ssh_cm, send_eof, 2) ->
- {removed,{ssh_connection,send_eof,2},"R14B"};
-obsolete_1(ssh_cm, send, A) when A =:= 3; A =:= 4 ->
- {removed,{ssh_connection,send,A},"R14B"};
-obsolete_1(ssh_cm, send_ack, A) when 3 =< A, A =< 5 ->
- {removed,{ssh_connection,send,[3,4]},"R14B"};
-obsolete_1(ssh_ssh, connect, A) when 1 =< A, A =< 3 ->
- {removed,{ssh,shell,A},"R14B"};
-obsolete_1(ssh_sshd, listen, A) when 0 =< A, A =< 3 ->
- {removed,{ssh,daemon,[1,2,3]},"R14B"};
-obsolete_1(ssh_sshd, stop, 1) ->
- {removed,{ssh,stop_listener,1},"R14B"};
-
%% Added in R13A.
obsolete_1(regexp, _, _) ->
{removed, "removed in R15; use the re module instead"};
-obsolete_1(lists, flat_length, 1) ->
- {removed,{lists,flatlength,1},"R14"};
-
-obsolete_1(ssh_sftp, connect, A) when 1 =< A, A =< 3 ->
- {removed,{ssh_sftp,start_channel,A},"R14B"};
-obsolete_1(ssh_sftp, stop, 1) ->
- {removed,{ssh_sftp,stop_channel,1},"R14B"};
-
-%% Added in R13B01.
-obsolete_1(ssl_pkix, decode_cert_file, A) when A =:= 1; A =:= 2 ->
- {removed,"removed in R14A; use public_key:pem_to_der/1 and public_key:pkix_decode_cert/2 instead"};
-obsolete_1(ssl_pkix, decode_cert, A) when A =:= 1; A =:= 2 ->
- {removed,{public_key,pkix_decode_cert,2},"R14A"};
-
%% Added in R13B04.
obsolete_1(erlang, concat_binary, 1) ->
{removed,{erlang,list_to_binary,1},"R15B"};
@@ -649,8 +542,12 @@ obsolete_1(random, _, _) ->
obsolete_1(code, rehash, 0) ->
{deprecated, "deprecated because the code path cache feature has been removed"};
+%% Removed in OTP 19.
+
obsolete_1(overload, _, _) ->
{removed, "removed in OTP 19"};
+obsolete_1(rpc, safe_multi_server_call, A) when A =:= 2; A =:= 3 ->
+ {removed, {rpc, multi_server_call, A}};
obsolete_1(_, _, _) ->
no.
diff --git a/lib/stdlib/src/pool.erl b/lib/stdlib/src/pool.erl
index 2112337f65..05950a1d7c 100644
--- a/lib/stdlib/src/pool.erl
+++ b/lib/stdlib/src/pool.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl
index 10c476a6f5..fdc2ae4070 100644
--- a/lib/stdlib/src/proc_lib.erl
+++ b/lib/stdlib/src/proc_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -48,7 +48,9 @@
| {'priority', priority_level()}
| {'min_heap_size', non_neg_integer()}
| {'min_bin_vheap_size', non_neg_integer()}
- | {'fullsweep_after', non_neg_integer()}.
+ | {'fullsweep_after', non_neg_integer()}
+ | {'message_queue_data',
+ 'off_heap' | 'on_heap' | 'mixed' }.
-type dict_or_pid() :: pid()
| (ProcInfo :: [_])
@@ -472,13 +474,15 @@ trans_init(gen,init_it,[gen_server,_,_,supervisor_bridge,[Module|_],_]) ->
{supervisor_bridge,Module,1};
trans_init(gen,init_it,[gen_server,_,_,_,supervisor_bridge,[Module|_],_]) ->
{supervisor_bridge,Module,1};
-trans_init(gen,init_it,[gen_server,_,_,Module,_,_]) ->
+trans_init(gen,init_it,[GenMod,_,_,Module,_,_])
+ when GenMod =:= gen_server;
+ GenMod =:= gen_statem;
+ GenMod =:= gen_fsm ->
{Module,init,1};
-trans_init(gen,init_it,[gen_server,_,_,_,Module|_]) ->
- {Module,init,1};
-trans_init(gen,init_it,[gen_fsm,_,_,Module,_,_]) ->
- {Module,init,1};
-trans_init(gen,init_it,[gen_fsm,_,_,_,Module|_]) ->
+trans_init(gen,init_it,[GenMod,_,_,_,Module|_])
+ when GenMod =:= gen_server;
+ GenMod =:= gen_statem;
+ GenMod =:= gen_fsm ->
{Module,init,1};
trans_init(gen,init_it,[gen_event|_]) ->
{gen_event,init_it,6};
diff --git a/lib/stdlib/src/proplists.erl b/lib/stdlib/src/proplists.erl
index 1840fa5cc0..8e99ec0ed9 100644
--- a/lib/stdlib/src/proplists.erl
+++ b/lib/stdlib/src/proplists.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl
index 2e65759d2a..d4d1904886 100644
--- a/lib/stdlib/src/queue.erl
+++ b/lib/stdlib/src/queue.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index d455abf7b0..93409d95df 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -44,11 +44,11 @@
%% This depends on the algorithm handler function
-type alg_seed() :: exs64_state() | exsplus_state() | exs1024_state().
%% This is the algorithm handler function within this module
--type alg_handler() :: #{type => alg(),
- max => integer(),
- next => fun(),
- uniform => fun(),
- uniform_n => fun()}.
+-type alg_handler() :: #{type := alg(),
+ max := integer(),
+ next := fun(),
+ uniform := fun(),
+ uniform_n := fun()}.
%% Internal state
-opaque state() :: {alg_handler(), alg_seed()}.
diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl
index 8b639dd0a7..46dabb4323 100644
--- a/lib/stdlib/src/random.erl
+++ b/lib/stdlib/src/random.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/re.erl b/lib/stdlib/src/re.erl
index 80bfe38970..52d3c35608 100644
--- a/lib/stdlib/src/re.erl
+++ b/lib/stdlib/src/re.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl
index cd435ff49c..3e70450320 100644
--- a/lib/stdlib/src/sets.erl
+++ b/lib/stdlib/src/sets.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/shell_default.erl b/lib/stdlib/src/shell_default.erl
index 4ef5e14db1..6947cf181b 100644
--- a/lib/stdlib/src/shell_default.erl
+++ b/lib/stdlib/src/shell_default.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl
index 4e629a5e56..5b5c328c0c 100644
--- a/lib/stdlib/src/slave.erl
+++ b/lib/stdlib/src/slave.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/sofs.erl b/lib/stdlib/src/sofs.erl
index bcd1fc11e2..b18df2ad09 100644
--- a/lib/stdlib/src/sofs.erl
+++ b/lib/stdlib/src/sofs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/stdlib.app.src b/lib/stdlib/src/stdlib.app.src
index b8a7973cf2..32bcdc4f2a 100644
--- a/lib/stdlib/src/stdlib.app.src
+++ b/lib/stdlib/src/stdlib.app.src
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,6 +65,7 @@
gen_event,
gen_fsm,
gen_server,
+ gen_statem,
io,
io_lib,
io_lib_format,
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 15d8857656..9877662743 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/string.erl b/lib/stdlib/src/string.erl
index 07659ed812..c659db78bd 100644
--- a/lib/stdlib/src/string.erl
+++ b/lib/stdlib/src/string.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl
index 0400c845ab..38b764541a 100644
--- a/lib/stdlib/src/supervisor.erl
+++ b/lib/stdlib/src/supervisor.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -57,8 +57,8 @@
| {'global', Name :: atom()}
| {'via', Module :: module(), Name :: any()}
| pid().
--type child_spec() :: #{id => child_id(), % mandatory
- start => mfargs(), % mandatory
+-type child_spec() :: #{id := child_id(), % mandatory
+ start := mfargs(), % mandatory
restart => restart(), % optional
shutdown => shutdown(), % optional
type => worker(), % optional
diff --git a/lib/stdlib/src/supervisor_bridge.erl b/lib/stdlib/src/supervisor_bridge.erl
index 18218b71ad..af1e046d30 100644
--- a/lib/stdlib/src/supervisor_bridge.erl
+++ b/lib/stdlib/src/supervisor_bridge.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/sys.erl b/lib/stdlib/src/sys.erl
index a7debb00f5..a6ecf03716 100644
--- a/lib/stdlib/src/sys.erl
+++ b/lib/stdlib/src/sys.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/timer.erl b/lib/stdlib/src/timer.erl
index f7530447bb..ca868627a9 100644
--- a/lib/stdlib/src/timer.erl
+++ b/lib/stdlib/src/timer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/src/win32reg.erl b/lib/stdlib/src/win32reg.erl
index 8074b2efda..8e82a79cbf 100644
--- a/lib/stdlib/src/win32reg.erl
+++ b/lib/stdlib/src/win32reg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/ExpandTestCaps.erl b/lib/stdlib/test/ExpandTestCaps.erl
index 1e5a1d68c3..7fb1107ae0 100644
--- a/lib/stdlib/test/ExpandTestCaps.erl
+++ b/lib/stdlib/test/ExpandTestCaps.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/ExpandTestCaps1.erl b/lib/stdlib/test/ExpandTestCaps1.erl
index e7ad0925f1..400a17b137 100644
--- a/lib/stdlib/test/ExpandTestCaps1.erl
+++ b/lib/stdlib/test/ExpandTestCaps1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index 287f63b2be..28c35aed55 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -46,6 +46,7 @@ MODULES= \
gen_event_SUITE \
gen_fsm_SUITE \
gen_server_SUITE \
+ gen_statem_SUITE \
id_transform_SUITE \
io_SUITE \
io_proto_SUITE \
diff --git a/lib/stdlib/test/array_SUITE.erl b/lib/stdlib/test/array_SUITE.erl
index 8d031ed490..5836f275ba 100644
--- a/lib/stdlib/test/array_SUITE.erl
+++ b/lib/stdlib/test/array_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/base64_SUITE.erl b/lib/stdlib/test/base64_SUITE.erl
index 074047c7c5..9176a3664a 100644
--- a/lib/stdlib/test/base64_SUITE.erl
+++ b/lib/stdlib/test/base64_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index bf6e30ec83..4521ecc0ef 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/binary_module_SUITE.erl b/lib/stdlib/test/binary_module_SUITE.erl
index 285740d3e0..55fdcdd054 100644
--- a/lib/stdlib/test/binary_module_SUITE.erl
+++ b/lib/stdlib/test/binary_module_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/c_SUITE.erl b/lib/stdlib/test/c_SUITE.erl
index 266918581b..4bd32a30f8 100644
--- a/lib/stdlib/test/c_SUITE.erl
+++ b/lib/stdlib/test/c_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/c_SUITE_data/m.erl b/lib/stdlib/test/c_SUITE_data/m.erl
index df1d5f4c01..5f758053e5 100644
--- a/lib/stdlib/test/c_SUITE_data/m.erl
+++ b/lib/stdlib/test/c_SUITE_data/m.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/calendar_SUITE.erl b/lib/stdlib/test/calendar_SUITE.erl
index 7372288492..20053dfe54 100644
--- a/lib/stdlib/test/calendar_SUITE.erl
+++ b/lib/stdlib/test/calendar_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/dict_SUITE.erl b/lib/stdlib/test/dict_SUITE.erl
index d315e6f673..47358d729f 100644
--- a/lib/stdlib/test/dict_SUITE.erl
+++ b/lib/stdlib/test/dict_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/digraph_SUITE.erl b/lib/stdlib/test/digraph_SUITE.erl
index 8825d3fc15..b5d3452616 100644
--- a/lib/stdlib/test/digraph_SUITE.erl
+++ b/lib/stdlib/test/digraph_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/digraph_utils_SUITE.erl b/lib/stdlib/test/digraph_utils_SUITE.erl
index 23520072f8..1dda4d6624 100644
--- a/lib/stdlib/test/digraph_utils_SUITE.erl
+++ b/lib/stdlib/test/digraph_utils_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/dummy1_h.erl b/lib/stdlib/test/dummy1_h.erl
index cdf9a305e1..c46b7cd303 100644
--- a/lib/stdlib/test/dummy1_h.erl
+++ b/lib/stdlib/test/dummy1_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/dummy_h.erl b/lib/stdlib/test/dummy_h.erl
index c81ea984f2..bc89cb4fde 100644
--- a/lib/stdlib/test/dummy_h.erl
+++ b/lib/stdlib/test/dummy_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/edlin_expand_SUITE.erl b/lib/stdlib/test/edlin_expand_SUITE.erl
index a53c5333d8..ccffa2e244 100644
--- a/lib/stdlib/test/edlin_expand_SUITE.erl
+++ b/lib/stdlib/test/edlin_expand_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index 3e1aaef378..ef2c912c57 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/epp_SUITE_data/mac.erl b/lib/stdlib/test/epp_SUITE_data/mac.erl
index 210c57e033..9215dcb342 100644
--- a/lib/stdlib/test/epp_SUITE_data/mac.erl
+++ b/lib/stdlib/test/epp_SUITE_data/mac.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/epp_SUITE_data/mac2.erl b/lib/stdlib/test/epp_SUITE_data/mac2.erl
index 0dd83ece06..315870517f 100644
--- a/lib/stdlib/test/epp_SUITE_data/mac2.erl
+++ b/lib/stdlib/test/epp_SUITE_data/mac2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/epp_SUITE_data/mac3.erl b/lib/stdlib/test/epp_SUITE_data/mac3.erl
index e7a3178db7..702a0c38a9 100644
--- a/lib/stdlib/test/epp_SUITE_data/mac3.erl
+++ b/lib/stdlib/test/epp_SUITE_data/mac3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/epp_SUITE_data/pmod.erl b/lib/stdlib/test/epp_SUITE_data/pmod.erl
index ff0ee81116..d846cd9ca2 100644
--- a/lib/stdlib/test/epp_SUITE_data/pmod.erl
+++ b/lib/stdlib/test/epp_SUITE_data/pmod.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/epp_SUITE_data/variable_1.erl b/lib/stdlib/test/epp_SUITE_data/variable_1.erl
index cd6a7bb69a..b731d11e87 100644
--- a/lib/stdlib/test/epp_SUITE_data/variable_1.erl
+++ b/lib/stdlib/test/epp_SUITE_data/variable_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/epp_SUITE_data/variable_1_include.hrl b/lib/stdlib/test/epp_SUITE_data/variable_1_include.hrl
index 30df6a3309..058f8dfd34 100644
--- a/lib/stdlib/test/epp_SUITE_data/variable_1_include.hrl
+++ b/lib/stdlib/test/epp_SUITE_data/variable_1_include.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/epp_SUITE_data/variable_1_include_dir.hrl b/lib/stdlib/test/epp_SUITE_data/variable_1_include_dir.hrl
index 4e2bd3e41f..453f32d766 100644
--- a/lib/stdlib/test/epp_SUITE_data/variable_1_include_dir.hrl
+++ b/lib/stdlib/test/epp_SUITE_data/variable_1_include_dir.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/erl_anno_SUITE.erl b/lib/stdlib/test/erl_anno_SUITE.erl
index 637a390c70..71ea9c3e1e 100644
--- a/lib/stdlib/test/erl_anno_SUITE.erl
+++ b/lib/stdlib/test/erl_anno_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl
index 7fed7fce56..3885f6648d 100644
--- a/lib/stdlib/test/erl_expand_records_SUITE.erl
+++ b/lib/stdlib/test/erl_expand_records_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/erl_internal_SUITE.erl b/lib/stdlib/test/erl_internal_SUITE.erl
index 45e67226b7..bfa48de6b7 100644
--- a/lib/stdlib/test/erl_internal_SUITE.erl
+++ b/lib/stdlib/test/erl_internal_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 29a389d4b8..b0214e5238 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -33,47 +33,38 @@
-define(privdir, proplists:get_value(priv_dir, Conf)).
-endif.
--export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2,
- init_per_testcase/2, end_per_testcase/2]).
-
--export([
- unused_vars_warn_basic/1,
- unused_vars_warn_lc/1,
- unused_vars_warn_rec/1,
- unused_vars_warn_fun/1,
- unused_vars_OTP_4858/1,
- unused_unsafe_vars_warn/1,
- export_vars_warn/1,
- shadow_vars/1,
- unused_import/1,
- unused_function/1,
- unsafe_vars/1,unsafe_vars2/1,
- unsafe_vars_try/1,
- unsized_binary_in_bin_gen_pattern/1,
- guard/1, otp_4886/1, otp_4988/1, otp_5091/1, otp_5276/1, otp_5338/1,
- otp_5362/1, otp_5371/1, otp_7227/1, otp_5494/1, otp_5644/1, otp_5878/1,
- otp_5917/1, otp_6585/1, otp_6885/1, otp_10436/1, otp_11254/1,
- otp_11772/1, otp_11771/1, otp_11872/1,
- export_all/1,
- bif_clash/1,
- behaviour_basic/1, behaviour_multiple/1, otp_11861/1,
- otp_7550/1,
- otp_8051/1,
- format_warn/1,
- on_load_successful/1, on_load_failing/1,
- too_many_arguments/1,
- basic_errors/1,bin_syntax_errors/1,
- predef/1,
- maps/1,maps_type/1,otp_11851/1,otp_11879/1,otp_13230/1,
- record_errors/1
- ]).
-
-init_per_testcase(_Case, Config) ->
- Config.
-
-end_per_testcase(_Case, _Config) ->
- ok.
+-export([all/0, suite/0, groups/0]).
+
+-export([unused_vars_warn_basic/1,
+ unused_vars_warn_lc/1,
+ unused_vars_warn_rec/1,
+ unused_vars_warn_fun/1,
+ unused_vars_OTP_4858/1,
+ unused_unsafe_vars_warn/1,
+ export_vars_warn/1,
+ shadow_vars/1,
+ unused_import/1,
+ unused_function/1,
+ unsafe_vars/1,unsafe_vars2/1,
+ unsafe_vars_try/1,
+ unsized_binary_in_bin_gen_pattern/1,
+ guard/1, otp_4886/1, otp_4988/1, otp_5091/1, otp_5276/1, otp_5338/1,
+ otp_5362/1, otp_5371/1, otp_7227/1, otp_5494/1, otp_5644/1, otp_5878/1,
+ otp_5917/1, otp_6585/1, otp_6885/1, otp_10436/1, otp_11254/1,
+ otp_11772/1, otp_11771/1, otp_11872/1,
+ export_all/1,
+ bif_clash/1,
+ behaviour_basic/1, behaviour_multiple/1, otp_11861/1,
+ otp_7550/1,
+ otp_8051/1,
+ format_warn/1,
+ on_load_successful/1, on_load_failing/1,
+ too_many_arguments/1,
+ basic_errors/1,bin_syntax_errors/1,
+ predef/1,
+ maps/1,maps_type/1,maps_parallel_match/1,
+ otp_11851/1,otp_11879/1,otp_13230/1,
+ record_errors/1]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -91,7 +82,8 @@ all() ->
bif_clash, behaviour_basic, behaviour_multiple, otp_11861,
otp_7550, otp_8051, format_warn, {group, on_load},
too_many_arguments, basic_errors, bin_syntax_errors, predef,
- maps, maps_type, otp_11851, otp_11879, otp_13230,
+ maps, maps_type, maps_parallel_match,
+ otp_11851, otp_11879, otp_13230,
record_errors].
groups() ->
@@ -101,19 +93,6 @@ groups() ->
unused_vars_OTP_4858, unused_unsafe_vars_warn]},
{on_load, [], [on_load_successful, on_load_failing]}].
-init_per_suite(Config) ->
- Config.
-
-end_per_suite(_Config) ->
- ok.
-
-init_per_group(_GroupName, Config) ->
- Config.
-
-end_per_group(_GroupName, Config) ->
- Config.
-
-
%% Warnings for unused variables in some simple cases.
unused_vars_warn_basic(Config) when is_list(Config) ->
@@ -2703,9 +2682,8 @@ otp_11872(Config) when is_list(Config) ->
t() ->
1.
">>,
- {error,[{6,erl_lint,{undefined_type,{product,0}}},
- {8,erl_lint,{undefined_type,{dict,0}}}],
- [{8,erl_lint,{new_builtin_type,{map,0}}}]} =
+ {errors,[{6,erl_lint,{undefined_type,{product,0}}},
+ {8,erl_lint,{builtin_type,{map,0}}}], []} =
run_test2(Config, Ts, []),
ok.
@@ -3584,8 +3562,6 @@ predef(Config) when is_list(Config) ->
ok.
maps(Config) ->
- %% TODO: test key patterns, not done because map patterns are going to be
- %% changed a lot.
Ts = [{illegal_map_construction,
<<"t() ->
#{ a := b,
@@ -3627,6 +3603,26 @@ maps(Config) ->
{errors,[{1,erl_lint,illegal_map_construction},
{1,erl_lint,{unbound_var,'X'}}],
[]}},
+ {legal_map_pattern,
+ <<"
+ -record(mapkey, {a=1,b=2}).
+ t(M,K1) ->
+ #{ a := 1,
+ $a := 1, $z := 99,
+ #{a=>val} := 2,
+ K1 := 1337,
+ #mapkey{a = 10} := wat,
+ #{{a,val}=>val} := 2,
+ #{ \"hi\" => wazzup, hi => ho } := yep,
+ ok := 1.0,
+ [3+3] := nope,
+ 1.0 := yep,
+ {3.0+3} := nope,
+ {yep} := yep
+ } = M.
+ ">>,
+ [],
+ []},
{legal_map_construction,
<<"t(V) -> #{ a => 1,
#{a=>V} => 2,
@@ -3689,7 +3685,52 @@ maps_type(Config) when is_list(Config) ->
t(M) -> M.
">>,
[],
- {warnings,[{3,erl_lint,{new_builtin_type,{map,0}}}]}}],
+ {errors,[{3,erl_lint,{builtin_type,{map,0}}}],[]}}],
+ [] = run(Config, Ts),
+ ok.
+
+maps_parallel_match(Config) when is_list(Config) ->
+ Ts = [{parallel_map_patterns_unbound1,
+ <<"
+ t(#{} = M) ->
+ #{K := V} = #{k := K} = M,
+ V.
+ ">>,
+ [],
+ {errors,[{3,erl_lint,{unbound_var,'K'}}],[]}},
+ {parallel_map_patterns_unbound2,
+ <<"
+ t(#{} = M) ->
+ #{K1 := V1} =
+ #{K2 := V2} =
+ #{k1 := K1,k2 := K2} = M,
+ [V1,V2].
+ ">>,
+ [],
+ {errors,[{3,erl_lint,{unbound_var,'K1'}},
+ {3,erl_lint,{unbound_var,'K1'}},
+ {4,erl_lint,{unbound_var,'K2'}},
+ {4,erl_lint,{unbound_var,'K2'}}],[]}},
+ {parallel_map_patterns_bound,
+ <<"
+ t(#{} = M,K1,K2) ->
+ #{K1 := V1} =
+ #{K2 := V2} =
+ #{k1 := K1,k2 := K2} = M,
+ [V1,V2].
+ ">>,
+ [],
+ []},
+ {parallel_map_patterns_literal,
+ <<"
+ t(#{} = M) ->
+ #{k1 := V1} =
+ #{k2 := V2} =
+ #{k1 := V1,k2 := V2} = M,
+ [V1,V2].
+ ">>,
+ [],
+ []}],
[] = run(Config, Ts),
ok.
diff --git a/lib/stdlib/test/erl_lint_SUITE_data/format.erl b/lib/stdlib/test/erl_lint_SUITE_data/format.erl
index ede89cd545..540befd146 100644
--- a/lib/stdlib/test/erl_lint_SUITE_data/format.erl
+++ b/lib/stdlib/test/erl_lint_SUITE_data/format.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 4d44f7686a..a48ba7b5b7 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -50,7 +50,7 @@
otp_6321/1, otp_6911/1, otp_6914/1, otp_8150/1, otp_8238/1,
otp_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1,
- otp_10302/1, otp_10820/1, otp_11100/1, otp_11861/1]).
+ otp_10302/1, otp_10820/1, otp_11100/1, otp_11861/1, pr_1014/1]).
%% Internal export.
-export([ehook/6]).
@@ -79,7 +79,7 @@ groups() ->
{tickets, [],
[otp_6321, otp_6911, otp_6914, otp_8150, otp_8238,
otp_8473, otp_8522, otp_8567, otp_8664, otp_9147,
- otp_10302, otp_10820, otp_11100, otp_11861]}].
+ otp_10302, otp_10820, otp_11100, otp_11861, pr_1014]}].
init_per_suite(Config) ->
Config.
@@ -902,6 +902,7 @@ maps_syntax(Config) when is_list(Config) ->
"-compile(export_all).\n"
"-type t1() :: map().\n"
"-type t2() :: #{ atom() => integer(), atom() => float() }.\n"
+ "-type t3() :: #{ atom() := integer(), atom() := float() }.\n"
"-type u() :: #{a => (I :: integer()) | (A :: atom()),\n"
" (X :: atom()) | (Y :: atom()) =>\n"
" (I :: integer()) | (A :: atom())}.\n"
@@ -1106,6 +1107,24 @@ otp_11861(Config) when is_list(Config) ->
pf(Form) ->
lists:flatten(erl_pp:form(Form, none)).
+pr_1014(Config) ->
+ ok = pp_forms(<<"-type t() :: #{_ => _}. ">>),
+ ok = pp_forms(<<"-type t() :: #{any() => _}. ">>),
+ ok = pp_forms(<<"-type t() :: #{_ => any()}. ">>),
+ ok = pp_forms(<<"-type t() :: #{any() => any()}. ">>),
+ ok = pp_forms(<<"-type t() :: #{...}. ">>),
+ ok = pp_forms(<<"-type t() :: #{atom() := integer(), ...}. ">>),
+
+ FileName = filename('pr_1014.erl', Config),
+ C = <<"-module pr_1014.\n"
+ "-compile export_all.\n"
+ "-type m() :: #{..., a := integer()}.\n">>,
+ ok = file:write_file(FileName, C),
+ {error,[{_,[{3,erl_parse,["syntax error before: ","','"]}]}],_} =
+ compile:file(FileName, [return]),
+
+ ok.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
compile(Config, Tests) ->
diff --git a/lib/stdlib/test/erl_scan_SUITE.erl b/lib/stdlib/test/erl_scan_SUITE.erl
index 9432edc00f..4ae734eb65 100644
--- a/lib/stdlib/test/erl_scan_SUITE.erl
+++ b/lib/stdlib/test/erl_scan_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/error_logger_forwarder.erl b/lib/stdlib/test/error_logger_forwarder.erl
index 7ac2cfce82..6bbf180585 100644
--- a/lib/stdlib/test/error_logger_forwarder.erl
+++ b/lib/stdlib/test/error_logger_forwarder.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
-module(error_logger_forwarder).
%% API.
--export([register/0]).
+-export([register/0, unregister/0]).
%% Internal export for error_logger.
-export([init/1,
@@ -33,6 +33,10 @@
register() ->
error_logger:add_report_handler(?MODULE, self()).
+unregister() ->
+ Self = self(),
+ Self = error_logger:delete_report_handler(?MODULE).
+
init(Tester) ->
{ok,Tester}.
diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl
index 30811f3fb4..2a34c7764f 100644
--- a/lib/stdlib/test/error_logger_h_SUITE.erl
+++ b/lib/stdlib/test/error_logger_h_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,11 +65,18 @@ logfile(Config) ->
error_logger:logfile(close),
analyse_events(Log, Ev, [AtNode], unlimited),
- [] = [{X, file:pid2name(X)} || X <- processes(), Data <- [process_info(X, [current_function])],
- Data =/= undefined,
- element(1, element(2, lists:keyfind(current_function, 1, Data)))
- =:= file_io_server,
- file:pid2name(X) =:= {ok, Log}],
+ %% Make sure that the file_io_server process has been stopped
+ [] = lists:filtermap(
+ fun(X) ->
+ case {process_info(X, [current_function]),
+ file:pid2name(X)} of
+ {[{current_function, {file_io_server, _, _}}],
+ {ok,P2N = Log}} ->
+ {true, {X, P2N}};
+ _ ->
+ false
+ end
+ end, processes()),
test_server:stop_node(Node),
@@ -112,7 +119,7 @@ tty(Config) ->
do_one_tty(Log, Ev, unlimited),
Pa = "-pa " ++ filename:dirname(code:which(?MODULE)),
- {ok,Node} = start_node(logfile, Pa),
+ {ok,Node} = start_node(tty, Pa),
tty_log_open(Log),
ok = rpc:call(Node, erlang, apply, [fun gen_events/1,[Ev]]),
tty_log_close(),
diff --git a/lib/stdlib/test/escript_SUITE.erl b/lib/stdlib/test/escript_SUITE.erl
index 30aaac70c2..28d69232a0 100644
--- a/lib/stdlib/test/escript_SUITE.erl
+++ b/lib/stdlib/test/escript_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict.erl
index 40758e3258..fc33d84445 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_app.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_app.erl
index a5bb5fa077..53174f2c6f 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_app.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_app.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_sup.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_sup.erl
index 8ed41a27ce..b1ab4b0597 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_sup.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dict/src/archive_script_dict_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy.erl
index a6685e8189..117ced4dc7 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_app.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_app.erl
index bbfdda7741..9d751615fc 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_app.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_app.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_sup.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_sup.erl
index 389d485f6d..a38958d004 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_sup.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_dummy/src/archive_script_dummy_sup.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main.erl
index 5ea114f25d..3b005e8aff 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl
index 6270a6bb60..1dc76b3dfa 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script/archive_script_main2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl b/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl
index 6c3ff1c463..7cffacdf97 100644
--- a/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl
+++ b/lib/stdlib/test/escript_SUITE_data/archive_script_file_access/archive_script_file_access.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index fd0ff0e252..15e3142408 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/ets_tough_SUITE.erl b/lib/stdlib/test/ets_tough_SUITE.erl
index c83c17217b..49aba7a529 100644
--- a/lib/stdlib/test/ets_tough_SUITE.erl
+++ b/lib/stdlib/test/ets_tough_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/expand_test.erl b/lib/stdlib/test/expand_test.erl
index 6c178a9270..5544923a12 100644
--- a/lib/stdlib/test/expand_test.erl
+++ b/lib/stdlib/test/expand_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/expand_test1.erl b/lib/stdlib/test/expand_test1.erl
index 9f1ea42eb7..abefaefcfd 100644
--- a/lib/stdlib/test/expand_test1.erl
+++ b/lib/stdlib/test/expand_test1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/file_sorter_SUITE.erl b/lib/stdlib/test/file_sorter_SUITE.erl
index 379f4d609b..5c0e2c1576 100644
--- a/lib/stdlib/test/file_sorter_SUITE.erl
+++ b/lib/stdlib/test/file_sorter_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/filelib_SUITE.erl b/lib/stdlib/test/filelib_SUITE.erl
index 16616a3207..4f8936edbf 100644
--- a/lib/stdlib/test/filelib_SUITE.erl
+++ b/lib/stdlib/test/filelib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl
index 3d6734b790..b7c4d3a6e5 100644
--- a/lib/stdlib/test/filename_SUITE.erl
+++ b/lib/stdlib/test/filename_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/fixtable_SUITE.erl b/lib/stdlib/test/fixtable_SUITE.erl
index de100a11d6..736e643974 100644
--- a/lib/stdlib/test/fixtable_SUITE.erl
+++ b/lib/stdlib/test/fixtable_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/format_SUITE.erl b/lib/stdlib/test/format_SUITE.erl
index b481d82ea6..176a40f1c5 100644
--- a/lib/stdlib/test/format_SUITE.erl
+++ b/lib/stdlib/test/format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/gen_event_SUITE.erl b/lib/stdlib/test/gen_event_SUITE.erl
index 4bad7801ff..4415c2d09d 100644
--- a/lib/stdlib/test/gen_event_SUITE.erl
+++ b/lib/stdlib/test/gen_event_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl
index f79a344c4e..d6bb002b5f 100644
--- a/lib/stdlib/test/gen_fsm_SUITE.erl
+++ b/lib/stdlib/test/gen_fsm_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -391,6 +391,12 @@ abnormal1(Config) when is_list(Config) ->
delayed = gen_fsm:sync_send_event(my_fsm, {delayed_answer,1}, 100),
{'EXIT',{timeout,_}} =
(catch gen_fsm:sync_send_event(my_fsm, {delayed_answer,10}, 1)),
+ receive
+ Msg ->
+ %% Ignore the delayed answer from the server.
+ io:format("Delayed message: ~p", [Msg])
+ end,
+
[] = get_messages(),
ok.
@@ -971,7 +977,7 @@ init(stop) ->
init(stop_shutdown) ->
{stop, shutdown};
init(sleep) ->
- ct:sleep(1000),
+ timer:sleep(1000),
{ok, idle, data};
init({timeout, T}) ->
{ok, idle, state, T};
@@ -1004,7 +1010,7 @@ idle(_, Data) ->
idle({connect, _Pid}, _From, Data) ->
{reply, accept, wfor_conf, Data};
idle({delayed_answer, T}, _From, Data) ->
- ct:sleep(T),
+ timer:sleep(T),
{reply, delayed, idle, Data};
idle(badreturn, _From, _Data) ->
badreturn;
diff --git a/lib/stdlib/test/gen_server_SUITE.erl b/lib/stdlib/test/gen_server_SUITE.erl
index 916fbc4e84..3242511f4a 100644
--- a/lib/stdlib/test/gen_server_SUITE.erl
+++ b/lib/stdlib/test/gen_server_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl
new file mode 100644
index 0000000000..3deb5fd986
--- /dev/null
+++ b/lib/stdlib/test/gen_statem_SUITE.erl
@@ -0,0 +1,1578 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2016. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+-module(gen_statem_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+-behaviour(gen_statem).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap,{minutes,1}}].
+
+all() ->
+ [{group, start},
+ {group, start_handle_event},
+ {group, stop},
+ {group, stop_handle_event},
+ {group, abnormal},
+ {group, abnormal_handle_event},
+ shutdown, stop_and_reply, event_order,
+ {group, sys},
+ hibernate, enter_loop].
+
+groups() ->
+ [{start, [],
+ [start1, start2, start3, start4, start5, start6, start7,
+ start8, start9, start10, start11, start12, next_events]},
+ {start_handle_event, [],
+ [start1, start2, start3, start4, start5, start6, start7,
+ start8, start9, start10, start11, start12, next_events]},
+ {stop, [],
+ [stop1, stop2, stop3, stop4, stop5, stop6, stop7, stop8, stop9, stop10]},
+ {stop_handle_event, [],
+ [stop1, stop2, stop3, stop4, stop5, stop6, stop7, stop8, stop9, stop10]},
+ {abnormal, [], [abnormal1, abnormal2]},
+ {abnormal_handle_event, [], [abnormal1, abnormal2]},
+ {sys, [],
+ [sys1, code_change,
+ call_format_status,
+ error_format_status, terminate_crash_format,
+ get_state, replace_state]},
+ {sys_handle_event, [],
+ [sys1,
+ call_format_status,
+ error_format_status, terminate_crash_format,
+ get_state, replace_state]}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(GroupName, Config)
+ when GroupName =:= start_handle_event;
+ GroupName =:= stop_handle_event;
+ GroupName =:= abnormal_handle_event;
+ GroupName =:= sys_handle_event ->
+ [{callback_mode,handle_event_function}|Config];
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+init_per_testcase(_CaseName, Config) ->
+ flush(),
+%%% dbg:tracer(),
+%%% dbg:p(all, c),
+%%% dbg:tpl(gen_statem, cx),
+%%% dbg:tpl(proc_lib, cx),
+%%% dbg:tpl(gen, cx),
+%%% dbg:tpl(sys, cx),
+ Config.
+
+end_per_testcase(_CaseName, Config) ->
+%%% dbg:stop(),
+ Config.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-define(EXPECT_FAILURE(Code, Reason),
+ try begin Code end of
+ Reason ->
+ ct:fail({unexpected,Reason})
+ catch
+ error:Reason -> Reason;
+ exit:Reason -> Reason
+ end).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% anonymous
+start1(Config) ->
+ %%OldFl = process_flag(trap_exit, true),
+
+ {ok,Pid0} = gen_statem:start_link(?MODULE, start_arg(Config, []), []),
+ ok = do_func_test(Pid0),
+ ok = do_sync_func_test(Pid0),
+ stop_it(Pid0),
+%% stopped = gen_statem:call(Pid0, stop),
+%% timeout =
+%% ?EXPECT_FAILURE(gen_statem:call(Pid0, hej), Reason),
+
+ %%process_flag(trap_exit, OldFl),
+ ok = verify_empty_msgq().
+
+%% anonymous w. shutdown
+start2(Config) ->
+ %% Dont link when shutdown
+ {ok,Pid0} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ ok = do_func_test(Pid0),
+ ok = do_sync_func_test(Pid0),
+ stopped = gen_statem:call(Pid0, {stop,shutdown}),
+ check_stopped(Pid0),
+ ok = verify_empty_msgq().
+
+%% anonymous with timeout
+start3(Config) ->
+ %%OldFl = process_flag(trap_exit, true),
+
+ {ok,Pid0} =
+ gen_statem:start(?MODULE, start_arg(Config, []), [{timeout,5}]),
+ ok = do_func_test(Pid0),
+ ok = do_sync_func_test(Pid0),
+ stop_it(Pid0),
+
+ {error,timeout} =
+ gen_statem:start(
+ ?MODULE, start_arg(Config, sleep), [{timeout,5}]),
+
+ %%process_flag(trap_exit, OldFl),
+ ok = verify_empty_msgq().
+
+%% anonymous with ignore
+start4(Config) ->
+ OldFl = process_flag(trap_exit, true),
+
+ ignore = gen_statem:start(?MODULE, start_arg(Config, ignore), []),
+
+ process_flag(trap_exit, OldFl),
+ ok = verify_empty_msgq().
+
+%% anonymous with stop
+start5(Config) ->
+ OldFl = process_flag(trap_exit, true),
+
+ {error,stopped} = gen_statem:start(?MODULE, start_arg(Config, stop), []),
+
+ process_flag(trap_exit, OldFl),
+ ok = verify_empty_msgq().
+
+%% anonymous linked
+start6(Config) ->
+ {ok,Pid} = gen_statem:start_link(?MODULE, start_arg(Config, []), []),
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ stop_it(Pid),
+
+ ok = verify_empty_msgq().
+
+%% global register linked
+start7(Config) ->
+ STM = {global,my_stm},
+
+ {ok,Pid} =
+ gen_statem:start_link(STM, ?MODULE, start_arg(Config, []), []),
+ {error,{already_started,Pid}} =
+ gen_statem:start_link(STM, ?MODULE, start_arg(Config, []), []),
+ {error,{already_started,Pid}} =
+ gen_statem:start(STM, ?MODULE, start_arg(Config, []), []),
+
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test(STM),
+ ok = do_sync_func_test(STM),
+ stop_it(STM),
+
+ ok = verify_empty_msgq().
+
+
+%% local register
+start8(Config) ->
+ %%OldFl = process_flag(trap_exit, true),
+ Name = my_stm,
+ STM = {local,Name},
+
+ {ok,Pid} =
+ gen_statem:start(STM, ?MODULE, start_arg(Config, []), []),
+ {error,{already_started,Pid}} =
+ gen_statem:start(STM, ?MODULE, start_arg(Config, []), []),
+
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test(Name),
+ ok = do_sync_func_test(Name),
+ stop_it(Pid),
+
+ %%process_flag(trap_exit, OldFl),
+ ok = verify_empty_msgq().
+
+%% local register linked
+start9(Config) ->
+ %%OldFl = process_flag(trap_exit, true),
+ Name = my_stm,
+ STM = {local,Name},
+
+ {ok,Pid} =
+ gen_statem:start_link(STM, ?MODULE, start_arg(Config, []), []),
+ {error,{already_started,Pid}} =
+ gen_statem:start(STM, ?MODULE, start_arg(Config, []), []),
+
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test(Name),
+ ok = do_sync_func_test(Name),
+ stop_it(Pid),
+
+ %%process_flag(trap_exit, OldFl),
+ ok = verify_empty_msgq().
+
+%% global register
+start10(Config) ->
+ STM = {global,my_stm},
+
+ {ok,Pid} =
+ gen_statem:start(STM, ?MODULE, start_arg(Config, []), []),
+ {error,{already_started,Pid}} =
+ gen_statem:start(STM, ?MODULE, start_arg(Config, []), []),
+ {error,{already_started,Pid}} =
+ gen_statem:start_link(STM, ?MODULE, start_arg(Config, []), []),
+
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test(STM),
+ ok = do_sync_func_test(STM),
+ stop_it(STM),
+
+ ok = verify_empty_msgq().
+
+%% Stop registered processes
+start11(Config) ->
+ Name = my_stm,
+ LocalSTM = {local,Name},
+ GlobalSTM = {global,Name},
+
+ {ok,Pid} =
+ gen_statem:start_link(LocalSTM, ?MODULE, start_arg(Config, []), []),
+ stop_it(Pid),
+
+ {ok,_Pid1} =
+ gen_statem:start_link(LocalSTM, ?MODULE, start_arg(Config, []), []),
+ stop_it(Name),
+
+ {ok,Pid2} =
+ gen_statem:start(GlobalSTM, ?MODULE, start_arg(Config, []), []),
+ stop_it(Pid2),
+ receive after 1 -> true end,
+ Result =
+ gen_statem:start(GlobalSTM, ?MODULE, start_arg(Config, []), []),
+ ct:log("Result = ~p~n",[Result]),
+ {ok,_Pid3} = Result,
+ stop_it(GlobalSTM),
+
+ ok = verify_empty_msgq().
+
+%% Via register linked
+start12(Config) ->
+ dummy_via:reset(),
+ VIA = {via,dummy_via,my_stm},
+
+ {ok,Pid} =
+ gen_statem:start_link(VIA, ?MODULE, start_arg(Config, []), []),
+ {error,{already_started,Pid}} =
+ gen_statem:start_link(VIA, ?MODULE, start_arg(Config, []), []),
+ {error,{already_started,Pid}} =
+ gen_statem:start(VIA, ?MODULE, start_arg(Config, []), []),
+
+ ok = do_func_test(Pid),
+ ok = do_sync_func_test(Pid),
+ ok = do_func_test(VIA),
+ ok = do_sync_func_test(VIA),
+ stop_it(VIA),
+
+ ok = verify_empty_msgq().
+
+
+%% Anonymous, reason 'normal'
+stop1(Config) ->
+ {ok,Pid} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ ok = gen_statem:stop(Pid),
+ false = erlang:is_process_alive(Pid),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason).
+
+%% Anonymous, other reason
+stop2(Config) ->
+ {ok,Pid} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ ok = gen_statem:stop(Pid, other_reason, infinity),
+ false = erlang:is_process_alive(Pid),
+ ok.
+
+%% Anonymous, invalid timeout
+stop3(Config) ->
+ {ok,Pid} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ _ =
+ ?EXPECT_FAILURE(
+ gen_statem:stop(Pid, other_reason, invalid_timeout),
+ Reason),
+ true = erlang:is_process_alive(Pid),
+ ok = gen_statem:stop(Pid),
+ false = erlang:is_process_alive(Pid),
+ ok.
+
+%% Registered name
+stop4(Config) ->
+ {ok,Pid} =
+ gen_statem:start(
+ {local,to_stop},?MODULE, start_arg(Config, []), []),
+ ok = gen_statem:stop(to_stop),
+ false = erlang:is_process_alive(Pid),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(to_stop), Reason),
+ ok.
+
+%% Registered name and local node
+stop5(Config) ->
+ Name = to_stop,
+ {ok,Pid} =
+ gen_statem:start(
+ {local,Name},?MODULE, start_arg(Config, []), []),
+ ok = gen_statem:stop({Name,node()}),
+ false = erlang:is_process_alive(Pid),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop({Name,node()}), Reason),
+ ok.
+
+%% Globally registered name
+stop6(Config) ->
+ STM = {global,to_stop},
+ {ok,Pid} = gen_statem:start(STM, ?MODULE, start_arg(Config, []), []),
+ ok = gen_statem:stop(STM),
+ false = erlang:is_process_alive(Pid),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason),
+ ok.
+
+%% 'via' registered name
+stop7(Config) ->
+ VIA = {via,dummy_via,to_stop},
+ dummy_via:reset(),
+ {ok,Pid} = gen_statem:start(VIA, ?MODULE, start_arg(Config, []), []),
+ ok = gen_statem:stop(VIA),
+ false = erlang:is_process_alive(Pid),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(VIA), Reason),
+ ok.
+
+%% Anonymous on remote node
+stop8(Config) ->
+ Node = gen_statem_stop8,
+ {ok,NodeName} = ct_slave:start(Node),
+ Dir = filename:dirname(code:which(?MODULE)),
+ rpc:call(NodeName, code, add_path, [Dir]),
+ {ok,Pid} =
+ rpc:call(
+ NodeName, gen_statem,start,
+ [?MODULE,start_arg(Config, []),[]]),
+ ok = gen_statem:stop(Pid),
+ false = rpc:call(NodeName, erlang, is_process_alive, [Pid]),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason1),
+ {ok,NodeName} = ct_slave:stop(Node),
+ {{nodedown,NodeName},{sys,terminate,_}} =
+ ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason2),
+ ok.
+
+%% Registered name on remote node
+stop9(Config) ->
+ Name = to_stop,
+ LocalSTM = {local,Name},
+ Node = gen_statem__stop9,
+ {ok,NodeName} = ct_slave:start(Node),
+ STM = {Name,NodeName},
+ Dir = filename:dirname(code:which(?MODULE)),
+ rpc:call(NodeName, code, add_path, [Dir]),
+ {ok,Pid} =
+ rpc:call(
+ NodeName, gen_statem, start,
+ [LocalSTM,?MODULE,start_arg(Config, []),[]]),
+ ok = gen_statem:stop(STM),
+ undefined = rpc:call(NodeName,erlang,whereis,[Name]),
+ false = rpc:call(NodeName,erlang,is_process_alive,[Pid]),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1),
+ {ok,NodeName} = ct_slave:stop(Node),
+ {{nodedown,NodeName},{sys,terminate,_}} =
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason2),
+ ok.
+
+%% Globally registered name on remote node
+stop10(Config) ->
+ Node = gen_statem_stop10,
+ STM = {global,to_stop},
+ {ok,NodeName} = ct_slave:start(Node),
+ Dir = filename:dirname(code:which(?MODULE)),
+ rpc:call(NodeName,code,add_path,[Dir]),
+ {ok,Pid} =
+ rpc:call(
+ NodeName, gen_statem, start,
+ [STM,?MODULE,start_arg(Config, []),[]]),
+ global:sync(),
+ ok = gen_statem:stop(STM),
+ false = rpc:call(NodeName, erlang, is_process_alive, [Pid]),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1),
+ {ok,NodeName} = ct_slave:stop(Node),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason2),
+ ok.
+
+%% Check that time outs in calls work
+abnormal1(Config) ->
+ Name = abnormal1,
+ LocalSTM = {local,Name},
+
+ {ok, _Pid} =
+ gen_statem:start(LocalSTM, ?MODULE, start_arg(Config, []), []),
+
+ %% timeout call.
+ delayed = gen_statem:call(Name, {delayed_answer,1}, 100),
+ {timeout,_} =
+ ?EXPECT_FAILURE(
+ gen_statem:call(Name, {delayed_answer,1000}, 10),
+ Reason),
+ ok = gen_statem:stop(Name),
+ ok = verify_empty_msgq().
+
+%% Check that bad return values makes the stm crash. Note that we must
+%% trap exit since we must link to get the real bad_return_ error
+abnormal2(Config) ->
+ OldFl = process_flag(trap_exit, true),
+ {ok,Pid} = gen_statem:start_link(?MODULE, start_arg(Config, []), []),
+
+ %% bad return value in the gen_statem loop
+ {{bad_return_value,badreturn},_} =
+ ?EXPECT_FAILURE(gen_statem:call(Pid, badreturn), Reason),
+ receive
+ {'EXIT',Pid,{bad_return_value,badreturn}} -> ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ process_flag(trap_exit, OldFl),
+ ok = verify_empty_msgq().
+
+shutdown(Config) ->
+ process_flag(trap_exit, true),
+
+ {ok,Pid0} = gen_statem:start_link(?MODULE, start_arg(Config, []), []),
+ ok = do_func_test(Pid0),
+ ok = do_sync_func_test(Pid0),
+ stopped = gen_statem:call(Pid0, {stop,{shutdown,reason}}),
+ receive {'EXIT',Pid0,{shutdown,reason}} -> ok end,
+ process_flag(trap_exit, false),
+
+ {noproc,_} =
+ ?EXPECT_FAILURE(gen_statem:call(Pid0, hej), Reason),
+
+ receive
+ Any ->
+ ct:log("Unexpected: ~p", [Any]),
+ ct:fail({unexpected,Any})
+ after 500 ->
+ ok
+ end.
+
+
+
+stop_and_reply(_Config) ->
+ process_flag(trap_exit, true),
+
+ Machine =
+ %% Abusing the internal format of From...
+ #{init =>
+ fun () ->
+ {ok,start,undefined}
+ end,
+ start =>
+ fun (cast, {echo,From1,Reply1}, undefined) ->
+ {next_state,wait,{reply,From1,Reply1}}
+ end,
+ wait =>
+ fun (cast, {stop_and_reply,Reason,From2,Reply2},R1) ->
+ {stop_and_reply,Reason,
+ [R1,{reply,From2,Reply2}]}
+ end},
+ {ok,STM} = gen_statem:start_link(?MODULE, {map_statem,Machine}, []),
+
+ Self = self(),
+ Tag1 = make_ref(),
+ gen_statem:cast(STM, {echo,{Self,Tag1},reply1}),
+ Tag2 = make_ref(),
+ gen_statem:cast(STM, {stop_and_reply,reason,{Self,Tag2},reply2}),
+ case flush() of
+ [{Tag1,reply1},{Tag2,reply2},{'EXIT',STM,reason}] ->
+ ok;
+ Other1 ->
+ ct:fail({unexpected,Other1})
+ end,
+
+ {noproc,_} =
+ ?EXPECT_FAILURE(gen_statem:call(STM, hej), Reason),
+ case flush() of
+ [] ->
+ ok;
+ Other2 ->
+ ct:fail({unexpected,Other2})
+ end.
+
+
+
+event_order(_Config) ->
+ process_flag(trap_exit, true),
+
+ Machine =
+ %% Abusing the internal format of From...
+ #{init =>
+ fun () ->
+ {ok,start,undefined}
+ end,
+ start =>
+ fun (cast, _, _) ->
+ {keep_state_and_data,postpone}; %% Handled in 'buffer'
+ ({call,From}, {buffer,Pid,[Tag3,Tag4,Tag5]},
+ undefined) ->
+ {next_state,buffer,[],
+ [{next_event,internal,{reply,{Pid,Tag3},ok3}},
+ {next_event,internal,{reply,{Pid,Tag4},ok4}},
+ {timeout,0,{reply,{Pid,Tag5},ok5}},
+ %% The timeout should not happen since there
+ %% are events that cancel it i.e next_event
+ %% and postponed
+ {reply,From,ok}]}
+ end,
+ buffer =>
+ fun (internal, Reply, Replies) ->
+ {keep_state,[Reply|Replies]};
+ (timeout, Reply, Replies) ->
+ {keep_state,[Reply|Replies]};
+ (cast, Reply, Replies) ->
+ {keep_state,[Reply|Replies]};
+ ({call,From}, {stop,Reason}, Replies) ->
+ {next_state,stop,undefined,
+ lists:reverse(
+ Replies,
+ [{reply,From,ok},
+ {next_event,internal,{stop,Reason}}])}
+ end,
+ stop =>
+ fun (internal, Result, undefined) ->
+ Result
+ end},
+
+ {ok,STM} = gen_statem:start_link(?MODULE, {map_statem,Machine}, []),
+ Self = self(),
+ Tag1 = make_ref(),
+ gen_statem:cast(STM, {reply,{Self,Tag1},ok1}),
+ Tag2 = make_ref(),
+ gen_statem:cast(STM, {reply,{Self,Tag2},ok2}),
+ Tag3 = make_ref(),
+ Tag4 = make_ref(),
+ Tag5 = make_ref(),
+ ok = gen_statem:call(STM, {buffer,Self,[Tag3,Tag4,Tag5]}),
+ ok = gen_statem:call(STM, {stop,reason}),
+ case flush() of
+ [{Tag3,ok3},{Tag4,ok4},{Tag1,ok1},{Tag2,ok2},
+ {'EXIT',STM,reason}] ->
+ ok;
+ Other1 ->
+ ct:fail({unexpected,Other1})
+ end,
+
+ {noproc,_} =
+ ?EXPECT_FAILURE(gen_statem:call(STM, hej), Reason),
+ case flush() of
+ [] ->
+ ok;
+ Other2 ->
+ ct:fail({unexpected,Other2})
+ end.
+
+
+
+sys1(Config) ->
+ {ok,Pid} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ {status, Pid, {module,gen_statem}, _} = sys:get_status(Pid),
+ sys:suspend(Pid),
+ Parent = self(),
+ Tag = make_ref(),
+ Caller =
+ spawn(
+ fun () ->
+ Parent ! {Tag,gen_statem:call(Pid, hej)}
+ end),
+ receive
+ {Tag,_} ->
+ ct:fail(should_be_suspended)
+ after 3000 ->
+ exit(Caller, ok)
+ end,
+
+ %% {timeout,_} =
+ %% ?EXPECT_FAILURE(gen_statem:call(Pid, hej), Reason),
+ sys:resume(Pid),
+ stop_it(Pid).
+
+code_change(Config) ->
+ {ok,Pid} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ {idle,data} = sys:get_state(Pid),
+ sys:suspend(Pid),
+ sys:change_code(Pid, ?MODULE, old_vsn, state_functions),
+ sys:resume(Pid),
+ {idle,{old_vsn,data,state_functions}} = sys:get_state(Pid),
+ stop_it(Pid).
+
+call_format_status(Config) ->
+ {ok,Pid} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ Status = sys:get_status(Pid),
+ {status,Pid,_Mod,[_PDict,running,_,_, Data]} = Status,
+ [format_status_called|_] = lists:reverse(Data),
+ stop_it(Pid),
+
+ %% check that format_status can handle a name being an atom (pid is
+ %% already checked by the previous test)
+ {ok, Pid2} =
+ gen_statem:start(
+ {local, gstm}, ?MODULE, start_arg(Config, []), []),
+ Status2 = sys:get_status(gstm),
+ {status,Pid2,_Mod,[_PDict2,running,_,_,Data2]} = Status2,
+ [format_status_called|_] = lists:reverse(Data2),
+ stop_it(Pid2),
+
+ %% check that format_status can handle a name being a term other than a
+ %% pid or atom
+ GlobalName1 = {global,"CallFormatStatus"},
+ {ok,Pid3} =
+ gen_statem:start(
+ GlobalName1, ?MODULE, start_arg(Config, []), []),
+ Status3 = sys:get_status(GlobalName1),
+ {status,Pid3,_Mod,[_PDict3,running,_,_,Data3]} = Status3,
+ [format_status_called|_] = lists:reverse(Data3),
+ stop_it(Pid3),
+ GlobalName2 = {global,{name, "term"}},
+ {ok,Pid4} =
+ gen_statem:start(
+ GlobalName2, ?MODULE, start_arg(Config, []), []),
+ Status4 = sys:get_status(GlobalName2),
+ {status,Pid4,_Mod,[_PDict4,running,_,_, Data4]} = Status4,
+ [format_status_called|_] = lists:reverse(Data4),
+ stop_it(Pid4),
+
+ %% check that format_status can handle a name being a term other than a
+ %% pid or atom
+ dummy_via:reset(),
+ ViaName1 = {via,dummy_via,"CallFormatStatus"},
+ {ok,Pid5} = gen_statem:start(ViaName1, ?MODULE, start_arg(Config, []), []),
+ Status5 = sys:get_status(ViaName1),
+ {status,Pid5,_Mod, [_PDict5,running,_,_, Data5]} = Status5,
+ [format_status_called|_] = lists:reverse(Data5),
+ stop_it(Pid5),
+ ViaName2 = {via,dummy_via,{name,"term"}},
+ {ok, Pid6} =
+ gen_statem:start(
+ ViaName2, ?MODULE, start_arg(Config, []), []),
+ Status6 = sys:get_status(ViaName2),
+ {status,Pid6,_Mod,[_PDict6,running,_,_,Data6]} = Status6,
+ [format_status_called|_] = lists:reverse(Data6),
+ stop_it(Pid6).
+
+
+
+error_format_status(Config) ->
+ error_logger_forwarder:register(),
+ OldFl = process_flag(trap_exit, true),
+ Data = "called format_status",
+ {ok,Pid} =
+ gen_statem:start(
+ ?MODULE, start_arg(Config, {data,Data}), []),
+ %% bad return value in the gen_statem loop
+ {{bad_return_value,badreturn},_} =
+ ?EXPECT_FAILURE(gen_statem:call(Pid, badreturn), Reason),
+ receive
+ {error,_,
+ {Pid,
+ "** State machine"++_,
+ [Pid,{{call,_},badreturn},
+ {formatted,idle,Data},
+ error,{bad_return_value,badreturn}|_]}} ->
+ ok;
+ Other when is_tuple(Other), element(1, Other) =:= error ->
+ error_logger_forwarder:unregister(),
+ ct:fail({unexpected,Other})
+ after 1000 ->
+ error_logger_forwarder:unregister(),
+ ct:fail(timeout)
+ end,
+ process_flag(trap_exit, OldFl),
+ error_logger_forwarder:unregister(),
+ receive
+ %% Comes with SASL
+ {error_report,_,{Pid,crash_report,_}} ->
+ ok
+ after 500 ->
+ ok
+ end,
+ ok = verify_empty_msgq().
+
+terminate_crash_format(Config) ->
+ error_logger_forwarder:register(),
+ OldFl = process_flag(trap_exit, true),
+ Data = crash_terminate,
+ {ok,Pid} =
+ gen_statem:start(
+ ?MODULE, start_arg(Config, {data,Data}), []),
+ stop_it(Pid),
+ Self = self(),
+ receive
+ {error,_GroupLeader,
+ {Pid,
+ "** State machine"++_,
+ [Pid,
+ {{call,{Self,_}},stop},
+ {formatted,idle,Data},
+ exit,{crash,terminate}|_]}} ->
+ ok;
+ Other when is_tuple(Other), element(1, Other) =:= error ->
+ error_logger_forwarder:unregister(),
+ ct:fail({unexpected,Other})
+ after 1000 ->
+ error_logger_forwarder:unregister(),
+ ct:fail(timeout)
+ end,
+ process_flag(trap_exit, OldFl),
+ error_logger_forwarder:unregister(),
+ receive
+ %% Comes with SASL
+ {error_report,_,{Pid,crash_report,_}} ->
+ ok
+ after 500 ->
+ ok
+ end,
+ ok = verify_empty_msgq().
+
+
+get_state(Config) ->
+ State = self(),
+ {ok,Pid} =
+ gen_statem:start(
+ ?MODULE, start_arg(Config, {data,State}), []),
+ {idle,State} = sys:get_state(Pid),
+ {idle,State} = sys:get_state(Pid, 5000),
+ stop_it(Pid),
+
+ %% check that get_state can handle a name being an atom (pid is
+ %% already checked by the previous test)
+ {ok,Pid2} =
+ gen_statem:start(
+ {local,gstm}, ?MODULE, start_arg(Config, {data,State}), []),
+ {idle,State} = sys:get_state(gstm),
+ {idle,State} = sys:get_state(gstm, 5000),
+ stop_it(Pid2),
+
+ %% check that get_state works when pid is sys suspended
+ {ok,Pid3} =
+ gen_statem:start(
+ ?MODULE, start_arg(Config, {data,State}), []),
+ {idle,State} = sys:get_state(Pid3),
+ ok = sys:suspend(Pid3),
+ {idle,State} = sys:get_state(Pid3, 5000),
+ ok = sys:resume(Pid3),
+ stop_it(Pid3),
+ ok = verify_empty_msgq().
+
+replace_state(Config) ->
+ State = self(),
+ {ok, Pid} =
+ gen_statem:start(
+ ?MODULE, start_arg(Config, {data,State}), []),
+ {idle,State} = sys:get_state(Pid),
+ NState1 = "replaced",
+ Replace1 = fun({StateName, _}) -> {StateName,NState1} end,
+ {idle,NState1} = sys:replace_state(Pid, Replace1),
+ {idle,NState1} = sys:get_state(Pid),
+ NState2 = "replaced again",
+ Replace2 = fun({idle, _}) -> {state0,NState2} end,
+ {state0,NState2} = sys:replace_state(Pid, Replace2, 5000),
+ {state0,NState2} = sys:get_state(Pid),
+ %% verify no change in state if replace function crashes
+ Replace3 = fun(_) -> error(fail) end,
+ {callback_failed,
+ {gen_statem,system_replace_state},{error,fail}} =
+ ?EXPECT_FAILURE(sys:replace_state(Pid, Replace3), Reason),
+ {state0, NState2} = sys:get_state(Pid),
+ %% verify state replaced if process sys suspended
+ ok = sys:suspend(Pid),
+ Suffix2 = " and again",
+ NState3 = NState2 ++ Suffix2,
+ Replace4 = fun({StateName, _}) -> {StateName, NState3} end,
+ {state0,NState3} = sys:replace_state(Pid, Replace4),
+ ok = sys:resume(Pid),
+ {state0,NState3} = sys:get_state(Pid, 5000),
+ stop_it(Pid),
+ ok = verify_empty_msgq().
+
+%% Hibernation
+hibernate(Config) ->
+ OldFl = process_flag(trap_exit, true),
+
+ {ok,Pid0} =
+ gen_statem:start_link(
+ ?MODULE, start_arg(Config, hiber_now), []),
+ is_in_erlang_hibernate(Pid0),
+ stop_it(Pid0),
+ receive
+ {'EXIT',Pid0,normal} -> ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ {ok,Pid} =
+ gen_statem:start_link(?MODULE, start_arg(Config, hiber), []),
+ true = ({current_function,{erlang,hibernate,3}} =/=
+ erlang:process_info(Pid,current_function)),
+ hibernating = gen_statem:call(Pid, hibernate_sync),
+ is_in_erlang_hibernate(Pid),
+ good_morning = gen_statem:call(Pid, wakeup_sync),
+ is_not_in_erlang_hibernate(Pid),
+ hibernating = gen_statem:call(Pid, hibernate_sync),
+ is_in_erlang_hibernate(Pid),
+ please_just_five_more = gen_statem:call(Pid, snooze_sync),
+ is_in_erlang_hibernate(Pid),
+ good_morning = gen_statem:call(Pid, wakeup_sync),
+ is_not_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, hibernate_async),
+ is_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, wakeup_async),
+ is_not_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, hibernate_async),
+ is_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, snooze_async),
+ is_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, wakeup_async),
+ is_not_in_erlang_hibernate(Pid),
+
+ Pid ! hibernate_later,
+ true =
+ ({current_function,{erlang,hibernate,3}} =/=
+ erlang:process_info(Pid, current_function)),
+ is_in_erlang_hibernate(Pid),
+
+ 'alive!' = gen_statem:call(Pid, 'alive?'),
+ true =
+ ({current_function,{erlang,hibernate,3}} =/=
+ erlang:process_info(Pid, current_function)),
+ Pid ! hibernate_now,
+ is_in_erlang_hibernate(Pid),
+
+ 'alive!' = gen_statem:call(Pid, 'alive?'),
+ true =
+ ({current_function,{erlang,hibernate,3}} =/=
+ erlang:process_info(Pid, current_function)),
+
+ hibernating = gen_statem:call(Pid, hibernate_sync),
+ is_in_erlang_hibernate(Pid),
+ good_morning = gen_statem:call(Pid, wakeup_sync),
+ is_not_in_erlang_hibernate(Pid),
+ hibernating = gen_statem:call(Pid, hibernate_sync),
+ is_in_erlang_hibernate(Pid),
+ please_just_five_more = gen_statem:call(Pid, snooze_sync),
+ is_in_erlang_hibernate(Pid),
+ good_morning = gen_statem:call(Pid, wakeup_sync),
+ is_not_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, hibernate_async),
+ is_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, wakeup_async),
+ is_not_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, hibernate_async),
+ is_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, snooze_async),
+ is_in_erlang_hibernate(Pid),
+ ok = gen_statem:cast(Pid, wakeup_async),
+ is_not_in_erlang_hibernate(Pid),
+
+ hibernating = gen_statem:call(Pid, hibernate_sync),
+ is_in_erlang_hibernate(Pid),
+ sys:suspend(Pid),
+ is_in_erlang_hibernate(Pid),
+ sys:resume(Pid),
+ is_in_erlang_hibernate(Pid),
+ receive after 1000 -> ok end,
+ is_in_erlang_hibernate(Pid),
+
+ good_morning = gen_statem:call(Pid, wakeup_sync),
+ is_not_in_erlang_hibernate(Pid),
+ stop_it(Pid),
+ process_flag(trap_exit, OldFl),
+ receive
+ {'EXIT',Pid,normal} -> ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+ ok = verify_empty_msgq().
+
+is_in_erlang_hibernate(Pid) ->
+ receive after 1 -> ok end,
+ is_in_erlang_hibernate_1(200, Pid).
+
+is_in_erlang_hibernate_1(0, Pid) ->
+ ct:log("~p\n", [erlang:process_info(Pid, current_function)]),
+ ct:fail(not_in_erlang_hibernate_3);
+is_in_erlang_hibernate_1(N, Pid) ->
+ {current_function,MFA} = erlang:process_info(Pid, current_function),
+ case MFA of
+ {erlang,hibernate,3} ->
+ ok;
+ _ ->
+ receive after 10 -> ok end,
+ is_in_erlang_hibernate_1(N-1, Pid)
+ end.
+
+is_not_in_erlang_hibernate(Pid) ->
+ receive after 1 -> ok end,
+ is_not_in_erlang_hibernate_1(200, Pid).
+
+is_not_in_erlang_hibernate_1(0, Pid) ->
+ ct:log("~p\n", [erlang:process_info(Pid, current_function)]),
+ ct:fail(not_in_erlang_hibernate_3);
+is_not_in_erlang_hibernate_1(N, Pid) ->
+ {current_function,MFA} = erlang:process_info(Pid, current_function),
+ case MFA of
+ {erlang,hibernate,3} ->
+ receive after 10 -> ok end,
+ is_not_in_erlang_hibernate_1(N-1, Pid);
+ _ ->
+ ok
+ end.
+
+
+enter_loop(_Config) ->
+ OldFlag = process_flag(trap_exit, true),
+
+ dummy_via:reset(),
+
+ %% Locally registered process + {local,Name}
+ {ok,Pid1a} =
+ proc_lib:start_link(?MODULE, enter_loop, [local,local]),
+ yes = gen_statem:call(Pid1a, 'alive?'),
+ stopped = gen_statem:call(Pid1a, stop),
+ receive
+ {'EXIT',Pid1a,normal} ->
+ ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ %% Unregistered process + {local,Name}
+ {ok,Pid1b} =
+ proc_lib:start_link(?MODULE, enter_loop, [anon,local]),
+ receive
+ {'EXIT',Pid1b,process_not_registered} ->
+ ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ %% Globally registered process + {global,Name}
+ {ok,Pid2a} =
+ proc_lib:start_link(?MODULE, enter_loop, [global,global]),
+ yes = gen_statem:call(Pid2a, 'alive?'),
+ stopped = gen_statem:call(Pid2a, stop),
+ receive
+ {'EXIT',Pid2a,normal} ->
+ ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ %% Unregistered process + {global,Name}
+ {ok,Pid2b} =
+ proc_lib:start_link(?MODULE, enter_loop, [anon,global]),
+ receive
+ {'EXIT',Pid2b,process_not_registered_globally} ->
+ ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ %% Unregistered process + no name
+ {ok,Pid3} =
+ proc_lib:start_link(?MODULE, enter_loop, [anon,anon]),
+ yes = gen_statem:call(Pid3, 'alive?'),
+ stopped = gen_statem:call(Pid3, stop),
+ receive
+ {'EXIT',Pid3,normal} ->
+ ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ %% Process not started using proc_lib
+ CallbackMode = state_functions,
+ Pid4 =
+ spawn_link(
+ gen_statem, enter_loop,
+ [?MODULE,[],CallbackMode,state0,[]]),
+ receive
+ {'EXIT',Pid4,process_was_not_started_by_proc_lib} ->
+ ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ %% Make sure I am the parent, ie that ordering a shutdown will
+ %% result in the process terminating with Reason==shutdown
+ {ok,Pid5} =
+ proc_lib:start_link(?MODULE, enter_loop, [anon,anon]),
+ yes = gen_statem:call(Pid5, 'alive?'),
+ exit(Pid5, shutdown),
+ receive
+ {'EXIT',Pid5,shutdown} ->
+ ok
+ after 5000 ->
+ ct:fail(gen_statem_did_not_die)
+ end,
+
+ %% Make sure gen_statem:enter_loop does not accept {local,Name}
+ %% when it's another process than the calling one which is
+ %% registered under that name
+ register(armitage, self()),
+ {ok,Pid6a} =
+ proc_lib:start_link(?MODULE, enter_loop, [anon,local]),
+ receive
+ {'EXIT',Pid6a,process_not_registered} ->
+ ok
+ after 1000 ->
+ ct:fail(gen_statem_started)
+ end,
+ unregister(armitage),
+
+ %% Make sure gen_statem:enter_loop does not accept {global,Name}
+ %% when it's another process than the calling one which is
+ %% registered under that name
+ global:register_name(armitage, self()),
+ {ok,Pid6b} =
+ proc_lib:start_link(?MODULE, enter_loop, [anon,global]),
+ receive
+ {'EXIT',Pid6b,process_not_registered_globally} ->
+ ok
+ after 1000 ->
+ ct:fail(gen_statem_started)
+ end,
+ global:unregister_name(armitage),
+
+ dummy_via:register_name(armitage, self()),
+ {ok,Pid6c} =
+ proc_lib:start_link(?MODULE, enter_loop, [anon,via]),
+ receive
+ {'EXIT',Pid6c,{process_not_registered_via,dummy_via}} ->
+ ok
+ after 1000 ->
+ ct:fail(
+ {gen_statem_started,
+ process_info(self(), messages)})
+ end,
+ dummy_via:unregister_name(armitage),
+
+ process_flag(trap_exit, OldFlag),
+ ok = verify_empty_msgq().
+
+enter_loop(Reg1, Reg2) ->
+ process_flag(trap_exit, true),
+ case Reg1 of
+ local -> register(armitage, self());
+ global -> global:register_name(armitage, self());
+ via -> dummy_via:register_name(armitage, self());
+ anon -> ignore
+ end,
+ proc_lib:init_ack({ok, self()}),
+ CallbackMode = state_functions,
+ case Reg2 of
+ local ->
+ gen_statem:enter_loop(
+ ?MODULE, [], CallbackMode, state0, [], {local,armitage});
+ global ->
+ gen_statem:enter_loop(
+ ?MODULE, [], CallbackMode, state0, [], {global,armitage});
+ via ->
+ gen_statem:enter_loop(
+ ?MODULE, [], CallbackMode, state0, [],
+ {via, dummy_via, armitage});
+ anon ->
+ gen_statem:enter_loop(
+ ?MODULE, [], CallbackMode, state0, [])
+ end.
+
+
+%% Test the order for multiple {next_event,T,C}
+next_events(Config) ->
+ {ok,Pid} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ ok = gen_statem:cast(Pid, next_event),
+ {state,next_events,[]} = gen_statem:call(Pid, get),
+ ok = gen_statem:stop(Pid),
+ false = erlang:is_process_alive(Pid),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason).
+
+
+%%
+%% Functionality check
+%%
+
+wfor(Msg) ->
+ receive
+ Msg -> ok
+ after 5000 ->
+ error(timeout)
+ end.
+
+
+stop_it(STM) ->
+ stopped = gen_statem:call(STM, stop),
+ check_stopped(STM).
+
+
+check_stopped(STM) ->
+ Call = there_you_are,
+ {_,{gen_statem,call,[_,Call,infinity]}} =
+ ?EXPECT_FAILURE(gen_statem:call(STM, Call), Reason),
+ ok.
+
+
+do_func_test(STM) ->
+ ok = gen_statem:cast(STM, {'alive?',self()}),
+ wfor(yes),
+ ok = do_connect(STM),
+ ok = gen_statem:cast(STM, {'alive?',self()}),
+ wfor(yes),
+ ?t:do_times(3, ?MODULE, do_msg, [STM]),
+ ok = gen_statem:cast(STM, {'alive?',self()}),
+ wfor(yes),
+ ok = do_disconnect(STM),
+ ok = gen_statem:cast(STM, {'alive?',self()}),
+ wfor(yes),
+ ok.
+
+
+do_connect(STM) ->
+ check_state(STM, idle),
+ gen_statem:cast(STM, {connect,self()}),
+ wfor(accept),
+ check_state(STM, wfor_conf),
+ Tag = make_ref(),
+ gen_statem:cast(STM, {ping,self(),Tag}),
+ gen_statem:cast(STM, confirm),
+ wfor({pong,Tag}),
+ check_state(STM, connected),
+ ok.
+
+do_msg(STM) ->
+ check_state(STM, connected),
+ R = make_ref(),
+ ok = gen_statem:cast(STM, {msg,self(),R}),
+ wfor({ack,R}).
+
+
+do_disconnect(STM) ->
+ ok = gen_statem:cast(STM, disconnect),
+ check_state(STM, idle).
+
+check_state(STM, State) ->
+ case gen_statem:call(STM, get) of
+ {state, State, _} -> ok
+ end.
+
+do_sync_func_test(STM) ->
+ yes = gen_statem:call(STM, 'alive?'),
+ ok = do_sync_connect(STM),
+ yes = gen_statem:call(STM, 'alive?'),
+ ?t:do_times(3, ?MODULE, do_sync_msg, [STM]),
+ yes = gen_statem:call(STM, 'alive?'),
+ ok = do_sync_disconnect(STM),
+ yes = gen_statem:call(STM, 'alive?'),
+ check_state(STM, idle),
+ ok = gen_statem:call(STM, {timeout,200}),
+ yes = gen_statem:call(STM, 'alive?'),
+ check_state(STM, idle),
+ ok.
+
+
+do_sync_connect(STM) ->
+ check_state(STM, idle),
+ accept = gen_statem:call(STM, connect),
+ check_state(STM, wfor_conf),
+ Tag = make_ref(),
+ gen_statem:cast(STM, {ping,self(),Tag}),
+ yes = gen_statem:call(STM, confirm),
+ wfor({pong,Tag}),
+ check_state(STM, connected),
+ ok.
+
+do_sync_msg(STM) ->
+ check_state(STM, connected),
+ R = make_ref(),
+ {ack,R} = gen_statem:call(STM, {msg,R}),
+ ok.
+
+do_sync_disconnect(STM) ->
+ yes = gen_statem:call(STM, disconnect),
+ check_state(STM, idle).
+
+
+verify_empty_msgq() ->
+ [] = flush(),
+ ok.
+
+start_arg(Config, Arg) ->
+ case lists:keyfind(callback_mode, 1, Config) of
+ {_,CallbackMode} ->
+ {callback_mode,CallbackMode,Arg};
+ false ->
+ Arg
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% The State Machine
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+init(ignore) ->
+ ignore;
+init(stop) ->
+ {stop,stopped};
+init(stop_shutdown) ->
+ {stop,shutdown};
+init(sleep) ->
+ ?t:sleep(1000),
+ {state_functions,idle,data};
+init(hiber) ->
+ {state_functions,hiber_idle,[]};
+init(hiber_now) ->
+ {state_functions,hiber_idle,[],[hibernate]};
+init({data, Data}) ->
+ {state_functions,idle,Data};
+init({callback_mode,CallbackMode,Arg}) ->
+ case init(Arg) of
+ {_,State,Data,Ops} ->
+ {CallbackMode,State,Data,Ops};
+ {_,State,Data} ->
+ {CallbackMode,State,Data};
+ Other ->
+ Other
+ end;
+init({map_statem,#{init := Init}=Machine}) ->
+ case Init() of
+ {ok,State,Data,Ops} ->
+ {handle_event_function,State,[Data|Machine],Ops};
+ {ok,State,Data} ->
+ {handle_event_function,State,[Data|Machine]};
+ Other ->
+ Other
+ end;
+init([]) ->
+ {state_functions,idle,data}.
+
+terminate(_, _State, crash_terminate) ->
+ exit({crash,terminate});
+terminate({From,stopped}, State, _Data) ->
+ From ! {self(),{stopped,State}},
+ ok;
+terminate(_Reason, _State, _Data) ->
+ ok.
+
+
+%% State functions
+
+idle(cast, {connect,Pid}, Data) ->
+ Pid ! accept,
+ {next_state,wfor_conf,Data,infinity}; % NoOp timeout just to test API
+idle({call,From}, connect, Data) ->
+ gen_statem:reply(From, accept),
+ {next_state,wfor_conf,Data,infinity}; % NoOp timeout just to test API
+idle(cast, badreturn, _Data) ->
+ badreturn;
+idle({call,_From}, badreturn, _Data) ->
+ badreturn;
+idle({call,From}, {delayed_answer,T}, Data) ->
+ receive
+ after T ->
+ gen_statem:reply({reply,From,delayed}),
+ throw({keep_state,Data})
+ end;
+idle({call,From}, {timeout,Time}, _Data) ->
+ {next_state,timeout,{From,Time},
+ {timeout,Time,idle}};
+idle(cast, next_event, _Data) ->
+ {next_state,next_events,[a,b,c],
+ [{next_event,internal,a},
+ {next_event,internal,b},
+ {next_event,internal,c}]};
+idle(Type, Content, Data) ->
+ case handle_common_events(Type, Content, idle, Data) of
+ undefined ->
+ case Type of
+ {call,From} ->
+ throw({keep_state,Data,[{reply,From,'eh?'}]});
+ _ ->
+ throw(
+ {stop,{unexpected,idle,Type,Content}})
+ end;
+ Result ->
+ Result
+ end.
+
+timeout(timeout, idle, {From,Time}) ->
+ TRef = erlang:start_timer(Time, self(), ok),
+ {keep_state,{From,TRef},0}; % Immediate timeout 0
+timeout(timeout, 0, {From,TRef}) ->
+ {next_state,timeout2,{From,TRef},
+ [{timeout,1,should_be_cancelled},
+ postpone]}; % Should cancel state timeout
+timeout(_, _, _) ->
+ keep_state_and_data.
+
+timeout2(timeout, 0, _) ->
+ keep_state_and_data;
+timeout2(timeout, Reason, _) ->
+ {stop,Reason};
+timeout2(info, {timeout,TRef,Result}, {From,TRef}) ->
+ gen_statem:reply([{reply,From,Result}]),
+ {next_state,idle,state};
+timeout2(_, _, _) ->
+ {keep_state_and_data,[]}.
+
+wfor_conf({call,From}, confirm, Data) ->
+ {next_state,connected,Data,
+ {reply,From,yes}};
+wfor_conf(cast, {ping,_,_}, _) ->
+ {keep_state_and_data,[postpone]};
+wfor_conf(cast, confirm, Data) ->
+ {next_state,connected,Data};
+wfor_conf(Type, Content, Data) ->
+ case handle_common_events(Type, Content, wfor_conf, Data) of
+ undefined ->
+ case Type of
+ {call,From} ->
+ {next_state,idle,Data,
+ [{reply,From,'eh?'}]};
+ _ ->
+ throw(keep_state_and_data)
+ end;
+ Result ->
+ Result
+ end.
+
+connected({call,From}, {msg,Ref}, Data) ->
+ {keep_state,Data,
+ {reply,From,{ack,Ref}}};
+connected(cast, {msg,From,Ref}, Data) ->
+ From ! {ack,Ref},
+ {keep_state,Data};
+connected({call,From}, disconnect, Data) ->
+ {next_state,idle,Data,
+ [{reply,From,yes}]};
+connected(cast, disconnect, Data) ->
+ {next_state,idle,Data};
+connected(cast, {ping,Pid,Tag}, Data) ->
+ Pid ! {pong,Tag},
+ {keep_state,Data};
+connected(Type, Content, Data) ->
+ case handle_common_events(Type, Content, connected, Data) of
+ undefined ->
+ case Type of
+ {call,From} ->
+ {keep_state,Data,
+ [{reply,From,'eh?'}]};
+ _ ->
+ {keep_state,Data}
+ end;
+ Result ->
+ Result
+ end.
+
+state0({call,From}, stop, Data) ->
+ {stop_and_reply,normal,[{reply,From,stopped}],Data};
+state0(Type, Content, Data) ->
+ case handle_common_events(Type, Content, state0, Data) of
+ undefined ->
+ {keep_state,Data};
+ Result ->
+ Result
+ end.
+
+hiber_idle({call,From}, 'alive?', Data) ->
+ {keep_state,Data,
+ [{reply,From,'alive!'}]};
+hiber_idle({call,From}, hibernate_sync, Data) ->
+ {next_state,hiber_wakeup,Data,
+ [{reply,From,hibernating},
+ hibernate]};
+hiber_idle(info, hibernate_later, _) ->
+ Tref = erlang:start_timer(1000, self(), hibernate),
+ {keep_state,Tref};
+hiber_idle(info, hibernate_now, Data) ->
+ {keep_state,Data,
+ [hibernate]};
+hiber_idle(info, {timeout,Tref,hibernate}, Tref) ->
+ {keep_state,[],
+ [hibernate]};
+hiber_idle(cast, hibernate_async, Data) ->
+ {next_state,hiber_wakeup,Data,
+ [hibernate]};
+hiber_idle(Type, Content, Data) ->
+ case handle_common_events(Type, Content, hiber_idle, Data) of
+ undefined ->
+ {keep_state,Data};
+ Result ->
+ Result
+ end.
+
+hiber_wakeup({call,From}, wakeup_sync, Data) ->
+ {next_state,hiber_idle,Data,
+ [{reply,From,good_morning}]};
+hiber_wakeup({call,From}, snooze_sync, Data) ->
+ {keep_state,Data,
+ [{reply,From,please_just_five_more},
+ hibernate]};
+hiber_wakeup(cast, wakeup_async, Data) ->
+ {next_state,hiber_idle,Data};
+hiber_wakeup(cast, snooze_async, Data) ->
+ {keep_state,Data,
+ [hibernate]};
+hiber_wakeup(Type, Content, Data) ->
+ case handle_common_events(Type, Content, hiber_wakeup, Data) of
+ undefined ->
+ {keep_state,Data};
+ Result ->
+ Result
+ end.
+
+next_events(internal, Msg, [Msg|Msgs]) ->
+ {keep_state,Msgs};
+next_events(Type, Content, Data) ->
+ case handle_common_events(Type, Content, next_events, Data) of
+ undefined ->
+ {keep_state,Data};
+ Result ->
+ Result
+ end.
+
+
+handle_common_events({call,From}, get, State, Data) ->
+ {keep_state,Data,
+ [{reply,From,{state,State,Data}}]};
+handle_common_events(cast, {get,Pid}, State, Data) ->
+ Pid ! {state,State,Data},
+ {keep_state,Data};
+handle_common_events({call,From}, stop, _, Data) ->
+ {stop_and_reply,normal,[{reply,From,stopped}],Data};
+handle_common_events(cast, stop, _, _) ->
+ stop;
+handle_common_events({call,From}, {stop,Reason}, _, Data) ->
+ {stop_and_reply,Reason,{reply,From,stopped},Data};
+handle_common_events(cast, {stop,Reason}, _, _) ->
+ {stop,Reason};
+handle_common_events({call,From}, 'alive?', _, Data) ->
+ {keep_state,Data,
+ [{reply,From,yes}]};
+handle_common_events(cast, {'alive?',Pid}, _, Data) ->
+ Pid ! yes,
+ {keep_state,Data};
+handle_common_events(_, _, _, _) ->
+ undefined.
+
+%% Wrapper state machine that uses a map state machine spec
+handle_event(
+ Type, Event, State, [Data|Machine])
+ when is_map(Machine) ->
+ #{State := HandleEvent} = Machine,
+ case
+ try HandleEvent(Type, Event, Data) of
+ Result ->
+ Result
+ catch
+ Result ->
+ Result
+ end of
+ {stop,Reason,NewData} ->
+ {stop,Reason,[NewData|Machine]};
+ {next_state,NewState,NewData} ->
+ {next_state,NewState,[NewData|Machine]};
+ {next_state,NewState,NewData,Ops} ->
+ {next_state,NewState,[NewData|Machine],Ops};
+ {keep_state,NewData} ->
+ {keep_state,[NewData|Machine]};
+ {keep_state,NewData,Ops} ->
+ {keep_state,[NewData|Machine],Ops};
+ Other ->
+ Other
+ end;
+%%
+%% Dispatcher to test callback_mode handle_event_function
+%%
+%% Wrap the state in a 1 element list just to test non-atom
+%% states. Note that the state from init/1 is not wrapped
+%% so both atom and non-atom states are tested.
+handle_event(Type, Event, State, Data) ->
+ StateName = unwrap_state(State),
+ try ?MODULE:StateName(Type, Event, Data) of
+ Result ->
+ wrap_result(Result)
+ catch
+ throw:Result ->
+ erlang:raise(
+ throw, wrap_result(Result), erlang:get_stacktrace())
+ end.
+
+unwrap_state([State]) ->
+ State;
+unwrap_state(State) ->
+ State.
+
+wrap_result(Result) ->
+ case Result of
+ {next_state,NewState,NewData} ->
+ {next_state,[NewState],NewData};
+ {next_state,NewState,NewData,StateOps} ->
+ {next_state,[NewState],NewData,StateOps};
+ Other ->
+ Other
+ end.
+
+
+
+code_change(OldVsn, State, Data, CallbackMode) ->
+ {CallbackMode,State,{OldVsn,Data,CallbackMode}}.
+
+format_status(terminate, [_Pdict,State,Data]) ->
+ {formatted,State,Data};
+format_status(normal, [_Pdict,_State,_Data]) ->
+ [format_status_called].
+
+flush() ->
+ receive
+ Msg ->
+ [Msg|flush()]
+ after 500 ->
+ []
+ end.
diff --git a/lib/stdlib/test/id_transform_SUITE.erl b/lib/stdlib/test/id_transform_SUITE.erl
index aaa6a758d5..54f452825f 100644
--- a/lib/stdlib/test/id_transform_SUITE.erl
+++ b/lib/stdlib/test/id_transform_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/id_transform_SUITE_data/External.hrl b/lib/stdlib/test/id_transform_SUITE_data/External.hrl
index 48f9cf7a01..447c12dbc1 100644
--- a/lib/stdlib/test/id_transform_SUITE_data/External.hrl
+++ b/lib/stdlib/test/id_transform_SUITE_data/External.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/id_transform_SUITE_data/m.hrl b/lib/stdlib/test/id_transform_SUITE_data/m.hrl
index 88fa280c14..6a7c08a92f 100644
--- a/lib/stdlib/test/id_transform_SUITE_data/m.hrl
+++ b/lib/stdlib/test/id_transform_SUITE_data/m.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/id_transform_SUITE_data/m_i.hrl b/lib/stdlib/test/id_transform_SUITE_data/m_i.hrl
index 48ae978cd3..cc6d18acc0 100644
--- a/lib/stdlib/test/id_transform_SUITE_data/m_i.hrl
+++ b/lib/stdlib/test/id_transform_SUITE_data/m_i.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/id_transform_SUITE_data/oe_ex.hrl b/lib/stdlib/test/id_transform_SUITE_data/oe_ex.hrl
index a3a892dba1..6878337ae9 100644
--- a/lib/stdlib/test/id_transform_SUITE_data/oe_ex.hrl
+++ b/lib/stdlib/test/id_transform_SUITE_data/oe_ex.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index ddc55b1466..be6b470ca7 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/io_proto_SUITE.erl b/lib/stdlib/test/io_proto_SUITE.erl
index ecd0d44db9..4e39f011f6 100644
--- a/lib/stdlib/test/io_proto_SUITE.erl
+++ b/lib/stdlib/test/io_proto_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index b21eb37ee3..531e97e8d6 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@
ufunsort_error/1,
zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1,
filter_partition/1,
+ join/1,
otp_5939/1, otp_6023/1, otp_6606/1, otp_7230/1,
suffix/1, subtract/1, droplast/1, hof/1]).
@@ -119,7 +120,7 @@ groups() ->
{tickets, [parallel], [otp_5939, otp_6023, otp_6606, otp_7230]},
{zip, [parallel], [zip_unzip, zip_unzip3, zipwith, zipwith3]},
{misc, [parallel], [reverse, member, dropwhile, takewhile,
- filter_partition, suffix, subtract,
+ filter_partition, suffix, subtract, join,
hof]}
].
@@ -2413,6 +2414,19 @@ zipwith3(Config) when is_list(Config) ->
ok.
+%% Test lists:join/2
+join(Config) when is_list(Config) ->
+ A = [a,b,c],
+ Sep = x,
+ [a,x,b,x,c] = lists:join(Sep, A),
+
+ B = [b],
+ [b] = lists:join(Sep, B),
+
+ C = [],
+ [] = lists:join(Sep, C),
+ ok.
+
%% Test lists:filter/2, lists:partition/2.
filter_partition(Config) when is_list(Config) ->
F = fun(I) -> I rem 2 =:= 0 end,
diff --git a/lib/stdlib/test/log_mf_h_SUITE.erl b/lib/stdlib/test/log_mf_h_SUITE.erl
index 9b543aa37c..894500dd79 100644
--- a/lib/stdlib/test/log_mf_h_SUITE.erl
+++ b/lib/stdlib/test/log_mf_h_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/maps_SUITE.erl b/lib/stdlib/test/maps_SUITE.erl
index 7f94b7bcb1..42e669a799 100644
--- a/lib/stdlib/test/maps_SUITE.erl
+++ b/lib/stdlib/test/maps_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,15 +25,10 @@
-include_lib("common_test/include/ct.hrl").
-%% Test server specific exports
--export([all/0]).
--export([suite/0]).
--export([init_per_suite/1]).
--export([end_per_suite/1]).
--export([init_per_testcase/2]).
--export([end_per_testcase/2]).
+-export([all/0, suite/0]).
--export([t_get_3/1, t_filter_2/1,
+-export([t_update_with_3/1, t_update_with_4/1,
+ t_get_3/1, t_filter_2/1,
t_fold_3/1,t_map_2/1,t_size_1/1,
t_with_2/1,t_without_2/1]).
@@ -41,29 +36,56 @@
%%-define(badarg(F,Args), {'EXIT', {badarg, [{maps,F,Args,_}|_]}}).
%% silly broken hipe
-define(badmap(V,F,_Args), {'EXIT', {{badmap,V}, [{maps,F,_,_}|_]}}).
+-define(badkey(K,F,_Args), {'EXIT', {{badkey,K}, [{maps,F,_,_}|_]}}).
-define(badarg(F,_Args), {'EXIT', {badarg, [{maps,F,_,_}|_]}}).
suite() ->
- [{ct_hooks, [ts_install_cth]},
+ [{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,1}}].
all() ->
- [t_get_3,t_filter_2,
+ [t_update_with_3,t_update_with_4,
+ t_get_3,t_filter_2,
t_fold_3,t_map_2,t_size_1,
t_with_2,t_without_2].
-init_per_suite(Config) ->
- Config.
+t_update_with_3(Config) when is_list(Config) ->
+ V1 = value1,
+ V2 = <<"value2">>,
+ V3 = "value3",
+ Map = #{ key1 => V1, key2 => V2, "key3" => V3 },
+ Fun = fun(V) -> [V,V,{V,V}] end,
-end_per_suite(_Config) ->
+ #{ key1 := [V1,V1,{V1,V1}] } = maps:update_with(key1,Fun,Map),
+ #{ key2 := [V2,V2,{V2,V2}] } = maps:update_with(key2,Fun,Map),
+ #{ "key3" := [V3,V3,{V3,V3}] } = maps:update_with("key3",Fun,Map),
+
+ %% error case
+ ?badmap(b,update_with,[[a,b],a,b]) = (catch maps:update_with([a,b],id(a),b)),
+ ?badarg(update_with,[[a,b],a,#{}]) = (catch maps:update_with([a,b],id(a),#{})),
+ ?badkey([a,b],update_with,[[a,b],Fun,#{}]) = (catch maps:update_with([a,b],Fun,#{})),
ok.
-init_per_testcase(_Case, Config) ->
- Config.
+t_update_with_4(Config) when is_list(Config) ->
+ V1 = value1,
+ V2 = <<"value2">>,
+ V3 = "value3",
+ Map = #{ key1 => V1, key2 => V2, "key3" => V3 },
+ Fun = fun(V) -> [V,V,{V,V}] end,
+ Init = 3,
+
+ #{ key1 := [V1,V1,{V1,V1}] } = maps:update_with(key1,Fun,Init,Map),
+ #{ key2 := [V2,V2,{V2,V2}] } = maps:update_with(key2,Fun,Init,Map),
+ #{ "key3" := [V3,V3,{V3,V3}] } = maps:update_with("key3",Fun,Init,Map),
-end_per_testcase(_Case, _Config) ->
+ #{ key3 := Init } = maps:update_with(key3,Fun,Init,Map),
+
+ %% error case
+ ?badmap(b,update_with,[[a,b],a,b]) = (catch maps:update_with([a,b],id(a),b)),
+ ?badarg(update_with,[[a,b],a,#{}]) = (catch maps:update_with([a,b],id(a),#{})),
ok.
+
t_get_3(Config) when is_list(Config) ->
Map = #{ key1 => value1, key2 => value2 },
DefaultValue = "Default value",
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index a8bd90de84..1c5faa960b 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/naughty_child.erl b/lib/stdlib/test/naughty_child.erl
index 0ea8f81d38..e159af5c01 100644
--- a/lib/stdlib/test/naughty_child.erl
+++ b/lib/stdlib/test/naughty_child.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/proc_lib_SUITE.erl b/lib/stdlib/test/proc_lib_SUITE.erl
index ebce74545a..416650e27e 100644
--- a/lib/stdlib/test/proc_lib_SUITE.erl
+++ b/lib/stdlib/test/proc_lib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index 75971bcf11..2bd940020c 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl b/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl
index d0cbc65d26..369101ab6c 100644
--- a/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl
+++ b/lib/stdlib/test/qlc_SUITE_data/join_info_compat.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/queue_SUITE.erl b/lib/stdlib/test/queue_SUITE.erl
index cd3f8e6e2f..569953dd9f 100644
--- a/lib/stdlib/test/queue_SUITE.erl
+++ b/lib/stdlib/test/queue_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index 6830101e96..1bcdc3ccd0 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -377,7 +377,7 @@ crypto_seed() ->
crypto_next(<<Num:64, Bin/binary>>) ->
{Num, Bin};
crypto_next(_) ->
- crypto_next(crypto:rand_bytes((64 div 8)*100)).
+ crypto_next(crypto:strong_rand_bytes((64 div 8)*100)).
crypto_uniform({Api, Data0}) ->
{Int, Data} = crypto_next(Data0),
diff --git a/lib/stdlib/test/random_SUITE.erl b/lib/stdlib/test/random_SUITE.erl
index 34b350e132..e9aa00dac8 100644
--- a/lib/stdlib/test/random_SUITE.erl
+++ b/lib/stdlib/test/random_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/random_iolist.erl b/lib/stdlib/test/random_iolist.erl
index 6da7da04de..555f063e0a 100644
--- a/lib/stdlib/test/random_iolist.erl
+++ b/lib/stdlib/test/random_iolist.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/random_unicode_list.erl b/lib/stdlib/test/random_unicode_list.erl
index 3bc86a8430..8db2fa8b56 100644
--- a/lib/stdlib/test/random_unicode_list.erl
+++ b/lib/stdlib/test/random_unicode_list.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl
index a937e7b1cf..52d3a9f797 100644
--- a/lib/stdlib/test/re_SUITE.erl
+++ b/lib/stdlib/test/re_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/re_testoutput1_replacement_test.erl b/lib/stdlib/test/re_testoutput1_replacement_test.erl
index 9081a18cd2..a40800d760 100644
--- a/lib/stdlib/test/re_testoutput1_replacement_test.erl
+++ b/lib/stdlib/test/re_testoutput1_replacement_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/re_testoutput1_split_test.erl b/lib/stdlib/test/re_testoutput1_split_test.erl
index 71728607bc..02987971fa 100644
--- a/lib/stdlib/test/re_testoutput1_split_test.erl
+++ b/lib/stdlib/test/re_testoutput1_split_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/run_pcre_tests.erl b/lib/stdlib/test/run_pcre_tests.erl
index 8b0373d062..ae56db59d6 100644
--- a/lib/stdlib/test/run_pcre_tests.erl
+++ b/lib/stdlib/test/run_pcre_tests.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/select_SUITE.erl b/lib/stdlib/test/select_SUITE.erl
index b7e86377c4..e999d040c9 100644
--- a/lib/stdlib/test/select_SUITE.erl
+++ b/lib/stdlib/test/select_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/sets_SUITE.erl b/lib/stdlib/test/sets_SUITE.erl
index b866cb62e0..bec38000b2 100644
--- a/lib/stdlib/test/sets_SUITE.erl
+++ b/lib/stdlib/test/sets_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index af735218b9..dc82e92876 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/slave_SUITE.erl b/lib/stdlib/test/slave_SUITE.erl
index dc14e4735a..25b706e81f 100644
--- a/lib/stdlib/test/slave_SUITE.erl
+++ b/lib/stdlib/test/slave_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/sofs_SUITE.erl b/lib/stdlib/test/sofs_SUITE.erl
index 2277b2d6fb..13c12ad2f2 100644
--- a/lib/stdlib/test/sofs_SUITE.erl
+++ b/lib/stdlib/test/sofs_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/stdlib_SUITE.erl b/lib/stdlib/test/stdlib_SUITE.erl
index f7064c4169..d55635a735 100644
--- a/lib/stdlib/test/stdlib_SUITE.erl
+++ b/lib/stdlib/test/stdlib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl
index b5d221732e..836f9e5142 100644
--- a/lib/stdlib/test/string_SUITE.erl
+++ b/lib/stdlib/test/string_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/supervisor_1.erl b/lib/stdlib/test/supervisor_1.erl
index 7a74f51429..419026749b 100644
--- a/lib/stdlib/test/supervisor_1.erl
+++ b/lib/stdlib/test/supervisor_1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/supervisor_2.erl b/lib/stdlib/test/supervisor_2.erl
index e3767c1fd4..0c15f253b3 100644
--- a/lib/stdlib/test/supervisor_2.erl
+++ b/lib/stdlib/test/supervisor_2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/supervisor_3.erl b/lib/stdlib/test/supervisor_3.erl
index 9ff7df2503..082cdf2153 100644
--- a/lib/stdlib/test/supervisor_3.erl
+++ b/lib/stdlib/test/supervisor_3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index 9de5a57e7f..3f1aa0e7a3 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/supervisor_bridge_SUITE.erl b/lib/stdlib/test/supervisor_bridge_SUITE.erl
index 029cb3fd7f..279ae91cdc 100644
--- a/lib/stdlib/test/supervisor_bridge_SUITE.erl
+++ b/lib/stdlib/test/supervisor_bridge_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/sys_SUITE.erl b/lib/stdlib/test/sys_SUITE.erl
index 39bc835824..b44df0fbda 100644
--- a/lib/stdlib/test/sys_SUITE.erl
+++ b/lib/stdlib/test/sys_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/sys_sp1.erl b/lib/stdlib/test/sys_sp1.erl
index b99914f4b7..571d0f3ed4 100644
--- a/lib/stdlib/test/sys_sp1.erl
+++ b/lib/stdlib/test/sys_sp1.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/sys_sp2.erl b/lib/stdlib/test/sys_sp2.erl
index e2784dc3ff..610665f8fe 100644
--- a/lib/stdlib/test/sys_sp2.erl
+++ b/lib/stdlib/test/sys_sp2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/tar_SUITE.erl b/lib/stdlib/test/tar_SUITE.erl
index 7f20851445..64dd41e75a 100644
--- a/lib/stdlib/test/tar_SUITE.erl
+++ b/lib/stdlib/test/tar_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/timer_SUITE.erl b/lib/stdlib/test/timer_SUITE.erl
index d4bbd39d50..5fc95b16a6 100644
--- a/lib/stdlib/test/timer_SUITE.erl
+++ b/lib/stdlib/test/timer_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/timer_simple_SUITE.erl b/lib/stdlib/test/timer_simple_SUITE.erl
index 64fce2a4b2..ff5116b8b6 100644
--- a/lib/stdlib/test/timer_simple_SUITE.erl
+++ b/lib/stdlib/test/timer_simple_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/unicode_SUITE.erl b/lib/stdlib/test/unicode_SUITE.erl
index d2ee5d19a4..81a591f433 100644
--- a/lib/stdlib/test/unicode_SUITE.erl
+++ b/lib/stdlib/test/unicode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/win32reg_SUITE.erl b/lib/stdlib/test/win32reg_SUITE.erl
index 62619dff47..5e44e16ddc 100644
--- a/lib/stdlib/test/win32reg_SUITE.erl
+++ b/lib/stdlib/test/win32reg_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/y2k_SUITE.erl b/lib/stdlib/test/y2k_SUITE.erl
index 7828eb26ed..129a279c28 100644
--- a/lib/stdlib/test/y2k_SUITE.erl
+++ b/lib/stdlib/test/y2k_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/zip_SUITE.erl b/lib/stdlib/test/zip_SUITE.erl
index 57ad869f24..2add5a39a2 100644
--- a/lib/stdlib/test/zip_SUITE.erl
+++ b/lib/stdlib/test/zip_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 5bac4be9d7..46e3ceac03 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 2.8
+STDLIB_VSN = 3.0