diff options
Diffstat (limited to 'system')
115 files changed, 2323 insertions, 410 deletions
diff --git a/system/COPYRIGHT b/system/COPYRIGHT index 0d0668974d..ef76b66f6b 100644 --- a/system/COPYRIGHT +++ b/system/COPYRIGHT @@ -5,7 +5,7 @@ This software is subject to the following Copyrights and Licenses: %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/system/README b/system/README deleted file mode 100644 index 97ec9177c4..0000000000 --- a/system/README +++ /dev/null @@ -1,78 +0,0 @@ -Erlang/OTP December 6, 2013 - - -Release of Erlang 5.10.4/OTP R16B03 - - -1. GENERAL - ------- - -1.1 Installation Guide - - The installation guide can be found in - - <inst-root>doc/installation_guide/users_guide.html - -1.2 Java - - The Java sources were compiled using Java version 1.5. - -1.3 Disk space - - An installation of Erlang/OTP needs approximately 300 MB of - disk space. - -1.4 The package contains HTML documentation. You can also get this - documentation preformatted for printing in PDF format from - - http://www.erlang.se/doc/ - - This site also contains HTML documentation for older releases - as a reference. - -1.5 The Erlang system can run old BEAM files compiled with R11B-2 - or later (and almost all BEAM files compiled with R11B-0 or - R11B-1). BEAM files from R10B or earlier are not supported. - - To get the best performance, you should recompile your - application code with the R15B compiler. - - -2. NOTES ABOUT THE SOLARIS VERSION - ------------------------------- - -2.1 For the Sparc Solaris environment, Solaris10 (2.10) and above is - supported. The emulator runs on older Solaris 8 (2.8) versions - and above. Older Solaris versions are neither tested nor supported. - Also an Ultrasparc (sun4u architecture) is required. - - -3. NOTES ABOUT THE VXWORKS VERSION - ------------------------------- - -3.1 The platform VxWorks is discontinued in the sense that only the - libraries (erl_interface and ic's libraries) are supported. The VxWorks - release is still packaged as a full release, but no support will be - available for anything but the communication libraries. - -4 NOTES ABOUT THE LINUX VERSIONS - ----------------------------- - -4.1 The following linux distributions/version combinations are supported - and tested: - - SuSE 10.1 x86, SuSE 10.1 x86_64, SuSE 11.0 x86, SuSE 11.0 x86_64 - -5. APPLICATIONS NOTES - ------------------ - - -6. MORE INFORMATION - ---------------- - - Commercial customers please visit http://www.erlang.se to find - releases and more information. Commercial support is given through - - Open source users please visit http://www.erlang.org and direct - problems to the open source community through the mailing list. diff --git a/system/doc/definitions/term.defs b/system/doc/definitions/term.defs index 6091a46a20..921175a7f0 100644 --- a/system/doc/definitions/term.defs +++ b/system/doc/definitions/term.defs @@ -76,6 +76,7 @@ the module Erlang in the application kernel","kenneth"}, {"gen_event","gen_event","A behaviour used for programming event handling mechanisms, such as alarm handlers, error loggers, and plug-and-play handlers.","mbj"}, {"gen_fsm","gen_fsm","A behaviour used for programming finite state machines.","mbj"}, {"gen_server","gen_server","A behaviour used for programming client-server processes.","mbj"}, +{"gen_statem","gen_statem","A behaviour used for programming generic state machines.","raimo"}, {"gterm","Global Glossary Database","A glossary database used to list common acronymns and defintions etc.","jocke"}, {"xref","xref","A cross reference tool that can be used for finding dependencies between functions, modules, applications and releases. Part of the Tools application.","gunilla"}, {"GSlong","Graphics System","A library module which provides a graphics interface for Erlang.","mbj"}, diff --git a/system/doc/design_principles/Makefile b/system/doc/design_principles/Makefile index 1f35ed8773..506c433f3b 100644 --- a/system/doc/design_principles/Makefile +++ b/system/doc/design_principles/Makefile @@ -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. @@ -58,6 +58,12 @@ GIF_FILES = \ sup5.gif \ sup6.gif +PNG_FILES = \ + code_lock.png \ + code_lock_2.png + +IMAGE_FILES = $(GIF_FILES) $(PNG_FILES) + XML_FILES = \ $(BOOK_FILES) $(XML_CHAPTER_FILES) \ $(XML_PART_FILES) @@ -84,13 +90,16 @@ DVIPS_FLAGS += $(HTMLDIR)/%.gif: %.gif $(INSTALL_DATA) $< $@ +$(HTMLDIR)/%.png: %.png + $(INSTALL_DATA) $< $@ + docs: html local_docs: PDFDIR=../../pdf -html: $(HTML_UG_FILE) gifs +html: $(HTML_UG_FILE) images -gifs: $(GIF_FILES:%=$(HTMLDIR)/%) +images: $(IMAGE_FILES:%=$(HTMLDIR)/%) debug opt: @@ -108,7 +117,7 @@ release_docs_spec: docs # $(INSTALL_DIR) "$(RELEASE_PATH)/pdf" # $(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELEASE_PATH)/pdf" $(INSTALL_DIR) $(RELSYSDIR) - $(INSTALL_DATA) $(GIF_FILES) $(HTMLDIR)/*.html \ + $(INSTALL_DATA) $(IMAGE_FILES) $(HTMLDIR)/*.html \ $(RELSYSDIR) diff --git a/system/doc/design_principles/applications.xml b/system/doc/design_principles/applications.xml index 4d73e0fc66..c673fde07e 100644 --- a/system/doc/design_principles/applications.xml +++ b/system/doc/design_principles/applications.xml @@ -4,14 +4,14 @@ <chapter> <header> <copyright> - <year>1997</year><year>2014</year> + <year>1997</year><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 @@ -19,7 +19,7 @@ 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>Applications</title> @@ -172,31 +172,136 @@ ch_app:stop([])</code> </section> <section> - <marker id="app_dir"></marker> - <title>Directory Structure</title> - <p>When packaging code using <c>systools</c>, the code for each - application is placed in a separate directory, - <c>lib/Application-Vsn</c>, where <c>Vsn</c> is the version number.</p> - <p>This can be useful to know, even if <c>systools</c> is not used, - since Erlang/OTP is packaged according to the OTP principles - and thus comes with this directory structure. The code server - (see the <c>code(3)</c> manual page in Kernel) automatically - uses code from - the directory with the highest version number, if more than one - version of an application is present.</p> - <p>The application directory structure can also be used in the - development environment. The version number can then - be omitted from the name.</p> - <p>The application directory has the following sub-directories:</p> - <list type="bulleted"> - <item><c>src</c> - Contains the Erlang source code.</item> - <item><c>ebin</c> - Contains the Erlang object code, the - <c>beam</c> files. The <c>.app</c> file is also placed here.</item> - <item><c>priv</c> - Used for application specific files. For - example, C executables are placed here. The function - <c>code:priv_dir/1</c> is to be used to access this directory.</item> - <item><c>include</c> - Used for include files.</item> - </list> + <marker id="app_dir"></marker> + <title>Directory Structure</title> + <p>When packaging code using <c>systools</c>, the code for each + application is placed in a separate directory, + <c>lib/Application-Vsn</c>, where <c>Vsn</c> is the version number.</p> + <p>This can be useful to know, even if <c>systools</c> is not used, + since Erlang/OTP is packaged according to the OTP principles + and thus comes with a specific directory structure. The code server + (see the <seealso marker="kernel:code"><c>code(3)</c></seealso> manual + page in Kernel) automatically uses code from + the directory with the highest version number, if more than one + version of an application is present.</p> + <section> + <title>Directory Structure guidelines for a Development Environment</title> + <p>Any directory structure for development will suffice as long as the released directory structure + adhere to the <seealso marker="#app_dir_released">description below</seealso>, + but it is encouraged that the same directory structure + also be used in a development environment. The version number should be omitted from the + application directory name since this is an artifact of the release step. + </p> + <p> Some sub-directories are <em>required</em>. Some sub-directories are <em>optional</em>, meaning that it should + only be used if the application itself requires it. Finally, some sub-directories are <em>recommended</em>, + meaning it is encouraged that it is used and used as described here. For example, both documentation + and tests are encouraged to exist in an application for it to be deemed a proper OTP application.</p> +<code type="none"> + ─ ${application} +  ├── doc + │   ├── internal + │   ├── examples + │   └── src +  ├── include +  ├── priv +  ├── src + │  └── ${application}.app.src +  └── test +</code> + <list type="bulleted"> + <item><c>src</c> - Required. Contains the Erlang source code, the source of the <c>.app</c> file + and internal include files used by the application itself. Additional sub-directories within + <c>src</c> can be used as namespaces to organize source files. These directories should never + be deeper than one level.</item> + <item><c>priv</c> - Optional. Used for application specific files. </item> + <item><c>include</c> - Optional. Used for public include files that must be reachable from + other applications.</item> + <item><c>doc</c> - Recommended. Any source documentation should be placed in sub-directories here.</item> + <item><c>doc/internal</c> - Recommended. Any documentation that describes implementation details about + this application, not intended for publication, should be placed here.</item> + <item><c>doc/examples</c> - Recommended. Source code for examples on how to use this application should + be placed here. It is encouraged that examples are sourced to the public documentation from + this directory.</item> + <item><c>doc/src</c> - Recommended. All source files for documentation, such as Markdown, AsciiDoc or + XML-files, should be placed here.</item> + <item><c>test</c> - Recommended. All files regarding tests, such as test suites and test specifications, + should be placed here. </item> + </list> + + <p>Other directories in the development environment may be needed. If source code from languages other + than Erlang is used, for instance C-code for NIFs, that code should be placed in a separate directory. + By convention it is recommended to prefix such directories with the language name, for example + <c>c_src</c> for C, <c>java_src</c> for Java or <c>go_src</c> for Go. Directories with <c>_src</c> + suffix indicates that it is a part of the application and the compilation step. The final build artifacts + should target the <c>priv/lib</c> or <c>priv/bin</c> directories.</p> + <p>The <c>priv</c> directory holds assets that the application needs during runtime. Executables should + reside in <c>priv/bin</c> and dynamically-linked libraries should reside in <c>priv/lib</c>. Other assets + are free to reside within the <c>priv</c> directory but it is recommended it does so in a structured manner.</p> + <p>Source files from other languages that generate Erlang code, such as ASN.1 or Mibs, should be placed + in directories, at the top level or in <c>src</c>, with the same name as the source language, for example + <c>asn1</c> and <c>mibs</c>. Build artifacts should be placed in their respective language directory, + such as <c>src</c> for Erlang code or <c>java_src</c> for Java code.</p> + <p>The <c>.app</c> file for release may reside in the <c>ebin</c>-directory in a development environment + but it is encouraged that this is an artifact of the build step. By convention a <c>.app.src</c> file + is used, which resides in the <c>src</c> directory. This file is nearly identical as the + <c>.app</c> file but certain fields may be replaced during the build step, such as the application version.</p> + <p>Directory names should not be capitalized.</p> + <p>It is encouraged to omit empty directories.</p> + + </section> + + <section> + <marker id="app_dir_released"></marker> + <title>Directory Structure for a Released System</title> + <p>A released application must follow a certain structure. + </p> +<code type="none"> + ─ ${application}-${version} +  ├── bin +  ├── doc + │   ├── html + │   ├── man[1-9] + │   ├── pdf + │   ├── internal + │   └── examples +  ├── ebin + │  └── ${application}.app +  ├── include +  ├── priv + │   ├── lib + │   └── bin +  └── src +</code> + <list type="bulleted"> + <item><c>src</c> - Optional. Contains the Erlang source code and internal include files + used by the application itself. This directory is no longer required in a released application.</item> + <item><c>ebin</c> - Required. Contains the Erlang object code, the <c>beam</c> files. + The <c>.app</c> file must also be placed here.</item> + <item><c>priv</c> - Optional. Used for application specific files. <c>code:priv_dir/1</c> + is to be used to access this directory.</item> + <item><c>priv/lib</c> - Recommended. Any shared-object files that are used by the application, + such as NIFs or linked-in-drivers, should be placed here.</item> + <item><c>priv/bin</c> - Recommended. Any executable that is used by the application, + such as port-programs, should be placed here.</item> + <item><c>include</c> - Optional. Used for public include files that must be reachable from + other applications.</item> + <item><c>bin</c> - Optional. Any executable that is a product of the application, + such as escripts or shell-scripts, should be placed here.</item> + <item><c>doc</c> - Optional. Any released documentation should be placed in + sub-directories here.</item> + <item><c>doc/man1</c> - Recommended. Man pages for Application executables.</item> + <item><c>doc/man3</c> - Recommended. Man pages for module APIs.</item> + <item><c>doc/man6</c> - Recommended. Man pages for Application overview.</item> + <item><c>doc/html</c> - Optional. HTML pages for the entire Application.</item> + <item><c>doc/pdf</c> - Optional. PDF documentation for the entire Application.</item> + </list> + + <p>The <c>src</c> directory could be useful to release for debugging purposes but is not required. + The <c>include</c> directory should only be released if the applications has public include files.</p> + <p>The only documentation that is recommended to be released in this way are the man pages. HTML and PDF + will normally be distributed in some other manner.</p> + <p>It is encouraged to omit empty directories.</p> + </section> </section> <section> @@ -381,4 +486,3 @@ application:start(Application, Type)</code> <c>shutdown</c>, not <c>normal</c>.</p> </section> </chapter> - diff --git a/system/doc/design_principles/appup_cookbook.xml b/system/doc/design_principles/appup_cookbook.xml index 31335197d7..4f23c42c59 100644 --- a/system/doc/design_principles/appup_cookbook.xml +++ b/system/doc/design_principles/appup_cookbook.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2014</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -50,7 +50,8 @@ <p>In a system implemented according to the OTP design principles, all processes, except system processes and special processes, reside in one of the behaviours <c>supervisor</c>, - <c>gen_server</c>, <c>gen_fsm</c>, or <c>gen_event</c>. These + <c>gen_server</c>, <c>gen_fsm</c>, + <c>gen_statem</c> or <c>gen_event</c>. These belong to the STDLIB application and upgrading/downgrading normally requires an emulator restart.</p> <p>OTP thus provides no support for changing residence modules except diff --git a/system/doc/design_principles/book.xml b/system/doc/design_principles/book.xml index 663551df2f..a734f1d1e4 100644 --- a/system/doc/design_principles/book.xml +++ b/system/doc/design_principles/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/system/doc/design_principles/code_lock.dia b/system/doc/design_principles/code_lock.dia Binary files differnew file mode 100644 index 0000000000..eaa2aca5b0 --- /dev/null +++ b/system/doc/design_principles/code_lock.dia diff --git a/system/doc/design_principles/code_lock.png b/system/doc/design_principles/code_lock.png Binary files differnew file mode 100644 index 0000000000..40bd35fc74 --- /dev/null +++ b/system/doc/design_principles/code_lock.png diff --git a/system/doc/design_principles/code_lock_2.dia b/system/doc/design_principles/code_lock_2.dia Binary files differnew file mode 100644 index 0000000000..3b9ba554d8 --- /dev/null +++ b/system/doc/design_principles/code_lock_2.dia diff --git a/system/doc/design_principles/code_lock_2.png b/system/doc/design_principles/code_lock_2.png Binary files differnew file mode 100644 index 0000000000..3aca9dd5aa --- /dev/null +++ b/system/doc/design_principles/code_lock_2.png diff --git a/system/doc/design_principles/des_princ.xml b/system/doc/design_principles/des_princ.xml index 0e087cf843..8ab8661c2d 100644 --- a/system/doc/design_principles/des_princ.xml +++ b/system/doc/design_principles/des_princ.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -226,7 +226,9 @@ free(Ch, {Alloc, Free} = Channels) -> <item><p><seealso marker="gen_server_concepts">gen_server</seealso></p> <p>For implementing the server of a client-server relation</p></item> <item><p><seealso marker="fsm">gen_fsm</seealso></p> - <p>For implementing finite-state machines</p></item> + <p>For implementing finite-state machines (Old)</p></item> + <item><p><seealso marker="statem">gen_statem</seealso></p> + <p>For implementing state machines (New)</p></item> <item><p><seealso marker="events">gen_event</seealso></p> <p>For implementing event handling functionality</p></item> <item><p><seealso marker="sup_princ">supervisor</seealso></p> diff --git a/system/doc/design_principles/distributed_applications.xml b/system/doc/design_principles/distributed_applications.xml index f1624a9ad7..a1a0149eb5 100644 --- a/system/doc/design_principles/distributed_applications.xml +++ b/system/doc/design_principles/distributed_applications.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/design_principles/events.xml b/system/doc/design_principles/events.xml index 3c9d0996dc..e37b8b460d 100644 --- a/system/doc/design_principles/events.xml +++ b/system/doc/design_principles/events.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/design_principles/fsm.xml b/system/doc/design_principles/fsm.xml index f58b50cbff..4f2b75e6e8 100644 --- a/system/doc/design_principles/fsm.xml +++ b/system/doc/design_principles/fsm.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -30,6 +30,16 @@ <file>fsm.xml</file> </header> <marker id="gen_fsm behaviour"></marker> + <note> + <p> + There is a new behaviour + <seealso marker="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>This section is to be read with the <c>gen_fsm(3)</c> manual page in STDLIB, where all interface functions and callback functions are described in detail.</p> diff --git a/system/doc/design_principles/gen_server_concepts.xml b/system/doc/design_principles/gen_server_concepts.xml index f8f98918fa..c1b98189d5 100644 --- a/system/doc/design_principles/gen_server_concepts.xml +++ b/system/doc/design_principles/gen_server_concepts.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/design_principles/included_applications.xml b/system/doc/design_principles/included_applications.xml index 3257795e5f..34501c0296 100644 --- a/system/doc/design_principles/included_applications.xml +++ b/system/doc/design_principles/included_applications.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/design_principles/part.xml b/system/doc/design_principles/part.xml index 42fd3beb6a..6495211e04 100644 --- a/system/doc/design_principles/part.xml +++ b/system/doc/design_principles/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -31,6 +31,7 @@ <xi:include href="des_princ.xml"/> <xi:include href="gen_server_concepts.xml"/> <xi:include href="fsm.xml"/> + <xi:include href="statem.xml"/> <xi:include href="events.xml"/> <xi:include href="sup_princ.xml"/> <xi:include href="spec_proc.xml"/> diff --git a/system/doc/design_principles/release_handling.xml b/system/doc/design_principles/release_handling.xml index 20ddc3dbf5..4f71ad4437 100644 --- a/system/doc/design_principles/release_handling.xml +++ b/system/doc/design_principles/release_handling.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2014</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -249,7 +249,7 @@ <p>If <c>Modules=dynamic</c>, which is the case for event managers, the event manager process informs the release handler about the list of currently installed event handlers - (<c>gen_fsm</c>), and it is checked if the module name is in + (<c>gen_event</c>), and it is checked if the module name is in this list instead.</p> <p>The release handler suspends, asks for code change, and resumes processes by calling the functions diff --git a/system/doc/design_principles/release_structure.xml b/system/doc/design_principles/release_structure.xml index 6e7ab06094..a0ab21c43f 100644 --- a/system/doc/design_principles/release_structure.xml +++ b/system/doc/design_principles/release_structure.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/design_principles/spec_proc.xml b/system/doc/design_principles/spec_proc.xml index 3d7a88da3f..5b156ac263 100644 --- a/system/doc/design_principles/spec_proc.xml +++ b/system/doc/design_principles/spec_proc.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2014</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -522,9 +522,36 @@ init(Parent, Name, Module) -> -module(db). -behaviour(simple_server). --export([init/0, handle_req/2, terminate/0]). +-export([init/1, handle_req/2, terminate/0]). ...</code> + + <p>The contracts specified with <c>-callback</c> attributes in + behaviour modules can be further refined by adding <c>-spec</c> + attributes in callback modules. This can be useful as + <c>-callback</c> contracts are usually generic. The same callback + module with contracts for the callbacks:</p> + + <code type="none"> +-module(db). +-behaviour(simple_server). + +-export([init/1, handle_req/2, terminate/0]). + +-record(state, {field1 :: [atom()], field2 :: integer()}). + +-type state() :: #state{}. +-type request() :: {'store', term(), term()}; + {'lookup', term()}. + +... + +-spec handle_req(request(), state()) -> {'ok', term()}. + +...</code> + + <p>Each <c>-spec</c> contract is to be a subtype of the respective + <c>-callback</c> contract.</p> + </section> </chapter> - diff --git a/system/doc/design_principles/statem.xml b/system/doc/design_principles/statem.xml new file mode 100644 index 0000000000..22b622ec5f --- /dev/null +++ b/system/doc/design_principles/statem.xml @@ -0,0 +1,1749 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2016</year><year>2017</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 Behavior</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>statem.xml</file> + </header> + <marker id="gen_statem Behaviour" /> + <p> + This section is to be read with the + <seealso marker="stdlib:gen_statem"><c>gen_statem(3)</c></seealso> + manual page in STDLIB, where all interface functions and callback + functions are described in detail. + </p> + <note> + <p> + This is a new behavior in Erlang/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. + Depending on user feedback, we do not expect + but can find it necessary to make minor + not backward compatible changes into Erlang/OTP 20.0. + </p> + </note> + +<!-- =================================================================== --> + + <section> + <marker id="Event-Driven State Machines" /> + <title>Event-Driven State Machines</title> + <p> + Established Automata Theory does not deal much with + how a state transition is triggered, + but assumes that the output is a function + of the input (and the state) and that they are + some kind of values. + </p> + <p> + For an Event-Driven State Machine, the input is an event + that triggers a state transition and the output + is actions executed during the state transition. + It can analogously to the mathematical model of a + Finite-State Machine be described as + a set of relations of the following form: + </p> + <pre> +State(S) x Event(E) -> Actions(A), State(S')</pre> + <p>These relations are interpreted as follows: + if we are in state <c>S</c> and event <c>E</c> occurs, we + are to perform actions <c>A</c> and make a transition to + state <c>S'</c>. Notice that <c>S'</c> can be equal to <c>S</c>. + </p> + <p> + As <c>A</c> and <c>S'</c> depend only on + <c>S</c> and <c>E</c>, the kind of state machine described + here is a Mealy Machine + (see, for example, the corresponding Wikipedia article). + </p> + <p> + Like most <c>gen_</c> behaviors, <c>gen_statem</c> keeps + a server <c>Data</c> besides the state. Because of this, and as + there is no restriction on the number of states + (assuming that there is enough virtual machine memory) + or on the number of distinct input events, + a state machine implemented with this behavior + is in fact Turing complete. + But it feels mostly like an Event-Driven Mealy Machine. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Callback Modes" /> + <title>Callback Modes</title> + <p> + The <c>gen_statem</c> behavior supports two callback modes: + </p> + <list type="bulleted"> + <item> + <p> + In mode + <seealso marker="stdlib:gen_statem#type-callback_mode"><c>state_functions</c></seealso>, + the state transition rules are written as some Erlang + functions, which conform to the following convention: + </p> + <pre> +StateName(EventType, EventContent, Data) -> + ... code for actions here ... + {next_state, NewStateName, NewData}. + </pre> + <p> + This form is used in most examples here for example in section + <seealso marker="#Example">Example</seealso>. + </p> + </item> + <item> + <p> + In mode + <seealso marker="stdlib:gen_statem#type-callback_mode"><c>handle_event_function</c></seealso>, + only one Erlang function provides all state transition rules: + </p> + <pre> +handle_event(EventType, EventContent, State, Data) -> + ... code for actions here ... + {next_state, NewState, NewData} + </pre> + <p> + See section + <seealso marker="#One Event Handler">One Event Handler</seealso> + for an example. + </p> + </item> + </list> + <p> + Both these modes allow other return tuples; see + <seealso marker="stdlib:gen_statem#Module:StateName/3"><c>Module:StateName/3</c></seealso> + in the <c>gen_statem</c> manual page. + These other return tuples can, for example, stop the machine, + execute state transition actions on the machine engine itself, + and send replies. + </p> + + <section> + <marker id="Choosing the Callback Mode" /> + <title>Choosing the Callback Mode</title> + <p> + The two + <seealso marker="#Callback Modes">callback modes</seealso> + give different possibilities + and restrictions, but one goal remains: + you want to handle all possible combinations of + events and states. + </p> + <p> + This can be done, for example, by focusing on one state at the time + and for every state ensure that all events are handled. + Alternatively, you can focus on one event at the time + and ensure that it is handled in every state. + You can also use a mix of these strategies. + </p> + <p> + With <c>state_functions</c>, you are restricted to use + atom-only states, and the <c>gen_statem</c> engine + branches depending on state name for you. + This encourages the callback module to gather + the implementation of all event actions particular + to one state in the same place in the code, + hence to focus on one state at the time. + </p> + <p> + This mode fits well when you have a regular state diagram, + like the ones in this chapter, which describes all events and actions + belonging to a state visually around that state, + and each state has its unique name. + </p> + <p> + With <c>handle_event_function</c>, you are free to mix strategies, + as all events and states are handled in the same callback function. + </p> + <p> + This mode works equally well when you want to focus on + one event at the time or on + one state at the time, but function + <seealso marker="stdlib:gen_statem#Module:handle_event/4"><c>Module:handle_event/4</c></seealso> + quickly grows too large to handle without branching to + helper functions. + </p> + <p> + The mode enables the use of non-atom states, for example, + complex states or even hierarchical states. + If, for example, a state diagram is largely alike + for the client side and the server side of a protocol, + you can have a state <c>{StateName,server}</c> or + <c>{StateName,client}</c>, + and make <c>StateName</c> determine where in the code + to handle most events in the state. + The second element of the tuple is then used to select + whether to handle special client-side or server-side events. + </p> + </section> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="State Enter Calls" /> + <title>State Enter Calls</title> + <p> + The <c>gen_statem</c> behavior can regardless of callback mode + automatically + <seealso marker="stdlib:gen_statem#type-state_enter"> + call the state callback + </seealso> + with special arguments whenever the state changes + so you can write state entry actions + near the rest of the state transition rules. + It typically looks like this: + </p> + <pre> +StateName(enter, _OldState, Data) -> + ... code for state entry actions here ... + {keep_state, NewData}; +StateName(EventType, EventContent, Data) -> + ... code for actions here ... + {next_state, NewStateName, NewData}.</pre> + <p> + Depending on how your state machine is specified, + this can be a very useful feature, + but it forces you to handle the state enter calls in all states. + See also the + <seealso marker="#State Entry Actions"> + State Entry Actions + </seealso> + chapter. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Actions" /> + <title>Actions</title> + <p> + In the first section + <seealso marker="#Event-Driven State Machines"> + Event-Driven State Machines + </seealso> + actions were mentioned as a part of + the general state machine model. These general actions + are implemented with the code that callback module + <c>gen_statem</c> executes in an event-handling + callback function before returning + to the <c>gen_statem</c> engine. + </p> + <p> + There are more specific state-transition actions + that a callback function can order the <c>gen_statem</c> + engine to do after the callback function return. + These are ordered by returning a list of + <seealso marker="stdlib:gen_statem#type-action">actions</seealso> + in the + <seealso marker="stdlib:gen_statem#type-state_callback_result">return tuple</seealso> + from the + <seealso marker="stdlib:gen_statem#Module:StateName/3">callback function</seealso>. + These state transition actions affect the <c>gen_statem</c> + engine itself and can do the following: + </p> + <list type="bulleted"> + <item> + <seealso marker="stdlib:gen_statem#type-postpone"> + Postpone + </seealso> + the current event, see section + <seealso marker="#Postponing Events">Postponing Events</seealso> + </item> + <item> + <seealso marker="stdlib:gen_statem#type-hibernate"> + Hibernate + </seealso> + the <c>gen_statem</c>, treated in + <seealso marker="#Hibernation">Hibernation</seealso> + </item> + <item> + Start a + <seealso marker="stdlib:gen_statem#type-state_timeout"> + state time-out</seealso>, + read more in section + <seealso marker="#State Time-Outs">State Time-Outs</seealso> + </item> + <item> + Start an + <seealso marker="stdlib:gen_statem#type-event_timeout">event time-out</seealso>, + see more in section + <seealso marker="#Event Time-Outs">Event Time-Outs</seealso> + </item> + <item> + <seealso marker="stdlib:gen_statem#type-reply_action"> + Reply + </seealso> + to a caller, mentioned at the end of section + <seealso marker="#All State Events">All State Events</seealso> + </item> + <item> + Generate the + <seealso marker="stdlib:gen_statem#type-action"> + next event + </seealso> + to handle, see section + <seealso marker="#Self-Generated Events">Self-Generated Events</seealso> + </item> + </list> + <p> + For details, see the + <seealso marker="stdlib:gen_statem#type-action"> + <c>gen_statem(3)</c> + </seealso> + manual page. + You can, for example, reply to many callers + and generate multiple next events to handle. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Event Types" /> + <title>Event Types</title> + <p> + Events are categorized in different + <seealso marker="stdlib:gen_statem#type-event_type">event types</seealso>. + Events of all types are handled in the same callback function, + for a given state, and the function gets + <c>EventType</c> and <c>EventContent</c> as arguments. + </p> + <p> + The following is a complete list of event types and where + they come from: + </p> + <taglist> + <tag><c>cast</c></tag> + <item> + Generated by + <seealso marker="stdlib:gen_statem#cast/2"><c>gen_statem:cast</c></seealso>. + </item> + <tag><c>{call,From}</c></tag> + <item> + Generated by + <seealso marker="stdlib:gen_statem#call/2"><c>gen_statem:call</c></seealso>, + where <c>From</c> is the reply address to use + when replying either through the state transition action + <c>{reply,From,Msg}</c> or by calling + <seealso marker="stdlib:gen_statem#reply/1"><c>gen_statem:reply</c></seealso>. + </item> + <tag><c>info</c></tag> + <item> + Generated by any regular process message sent to + the <c>gen_statem</c> process. + </item> + <tag><c>state_timeout</c></tag> + <item> + Generated by state transition action + <seealso marker="stdlib:gen_statem#type-state_timeout"> + <c>{state_timeout,Time,EventContent}</c> + </seealso> + state timer timing out. + </item> + <tag><c>timeout</c></tag> + <item> + Generated by state transition action + <seealso marker="stdlib:gen_statem#type-event_timeout"> + <c>{timeout,Time,EventContent}</c> + </seealso> + (or its short form <c>Time</c>) + event timer timing out. + </item> + <tag><c>internal</c></tag> + <item> + Generated by state transition + <seealso marker="stdlib:gen_statem#type-action">action</seealso> + <c>{next_event,internal,EventContent}</c>. + All event types above can also be generated using + <c>{next_event,EventType,EventContent}</c>. + </item> + </taglist> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Example" /> + <title>Example</title> + <p> + This example starts off as equivalent to the example in section + <seealso marker="fsm"><c>gen_fsm</c> Behavior</seealso>. + In later sections, additions and tweaks are made + using features in <c>gen_statem</c> that <c>gen_fsm</c> does not have. + The end of this chapter provides the example again + with all the added features. + </p> + <p> + A door with a code lock can be seen as a state machine. + Initially, the door is locked. When someone presses a button, + an event is generated. + Depending on what buttons have been pressed before, + the sequence so far can be correct, incomplete, or wrong. + If correct, the door is unlocked for 10 seconds (10,000 milliseconds). + If incomplete, we wait for another button to be pressed. If + wrong, we start all over, waiting for a new button sequence. + </p> + <image file="../design_principles/code_lock.png"> + <icaption>Code Lock State Diagram</icaption> + </image> + <p> + This code lock state machine can be implemented using + <c>gen_statem</c> with the following callback module: + </p> + <code type="erl"><![CDATA[ +-module(code_lock). +-behaviour(gen_statem). +-define(NAME, code_lock). + +-export([start_link/1]). +-export([button/1]). +-export([init/1,callback_mode/0,terminate/3,code_change/4]). +-export([locked/3,open/3]). + +start_link(Code) -> + gen_statem:start_link({local,?NAME}, ?MODULE, Code, []). + +button(Digit) -> + gen_statem:cast(?NAME, {button,Digit}). + +init(Code) -> + do_lock(), + Data = #{code => Code, remaining => Code}, + {ok, locked, Data}. + +callback_mode() -> + state_functions. + +locked( + cast, {button,Digit}, + #{code := Code, remaining := Remaining} = Data) -> + case Remaining of + [Digit] -> + do_unlock(), + {next_state, open, Data#{remaining := Code}, + [{state_timeout,10000,lock}]; + [Digit|Rest] -> % Incomplete + {next_state, locked, Data#{remaining := Rest}}; + _Wrong -> + {next_state, locked, Data#{remaining := Code}} + end. + +open(state_timeout, lock, Data) -> + do_lock(), + {next_state, locked, Data}; +open(cast, {button,_}, Data) -> + {next_state, open, Data}. + +do_lock() -> + io:format("Lock~n", []). +do_unlock() -> + io:format("Unlock~n", []). + +terminate(_Reason, State, _Data) -> + State =/= locked andalso do_lock(), + ok. +code_change(_Vsn, State, Data, _Extra) -> + {ok, State, Data}. + ]]></code> + <p>The code is explained in the next sections.</p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Starting gen_statem" /> + <title>Starting gen_statem</title> + <p> + In the example in the previous section, <c>gen_statem</c> is + started by calling <c>code_lock:start_link(Code)</c>: + </p> + <code type="erl"><![CDATA[ +start_link(Code) -> + gen_statem:start_link({local,?NAME}, ?MODULE, Code, []). + ]]></code> + <p> + <c>start_link</c> calls function + <seealso marker="stdlib:gen_statem#start_link/4"><c>gen_statem:start_link/4</c></seealso>, + which spawns and links to a new process, a <c>gen_statem</c>. + </p> + <list type="bulleted"> + <item> + <p> + The first argument, <c>{local,?NAME}</c>, specifies + the name. In this case, the <c>gen_statem</c> is locally + registered as <c>code_lock</c> through the macro <c>?NAME</c>. + </p> + <p> + If the name is omitted, the <c>gen_statem</c> is not registered. + Instead its pid must be used. The name can also be specified + as <c>{global,Name}</c>, then the <c>gen_statem</c> is + registered using + <seealso marker="kernel:global#register_name/2"><c>global:register_name/2</c></seealso> + in Kernel. + </p> + </item> + <item> + <p> + The second argument, <c>?MODULE</c>, is the name of + the callback module, that is, the module where the callback + functions are located, which is this module. + </p> + <p> + The interface functions (<c>start_link/1</c> and <c>button/1</c>) + are located in the same module as the callback functions + (<c>init/1</c>, <c>locked/3</c>, and <c>open/3</c>). + It is normally good programming practice to have the client-side + code and the server-side code contained in one module. + </p> + </item> + <item> + <p> + The third argument, <c>Code</c>, is a list of digits, which + is the correct unlock code that is passed + to callback function <c>init/1</c>. + </p> + </item> + <item> + <p> + The fourth argument, <c>[]</c>, is a list of options. + For the available options, see + <seealso marker="stdlib:gen_statem#start_link/3"><c>gen_statem:start_link/3</c></seealso>. + </p> + </item> + </list> + <p> + If name registration succeeds, the new <c>gen_statem</c> process + calls callback function <c>code_lock:init(Code)</c>. + This function is expected to return <c>{ok, State, Data}</c>, + where <c>State</c> is the initial state of the <c>gen_statem</c>, + in this case <c>locked</c>; assuming that the door is locked to begin + with. <c>Data</c> is the internal server data of the <c>gen_statem</c>. + Here the server data is a <seealso marker="stdlib:maps">map</seealso> + with key <c>code</c> that stores + the correct button sequence, and key <c>remaining</c> + that stores the remaining correct button sequence + (the same as the <c>code</c> to begin with). + </p> + + <code type="erl"><![CDATA[ +init(Code) -> + do_lock(), + Data = #{code => Code, remaining => Code}, + {ok,locked,Data}. + ]]></code> + <p>Function + <seealso marker="stdlib:gen_statem#start_link/3"><c>gen_statem:start_link</c></seealso> + is synchronous. It does not return until the <c>gen_statem</c> + is initialized and is ready to receive events. + </p> + <p> + Function + <seealso marker="stdlib:gen_statem#start_link/3"><c>gen_statem:start_link</c></seealso> + must be used if the <c>gen_statem</c> + is part of a supervision tree, that is, started by a supervisor. + Another function, + <seealso marker="stdlib:gen_statem#start/3"><c>gen_statem:start</c></seealso> + can be used to start a standalone <c>gen_statem</c>, that is, + a <c>gen_statem</c> that is not part of a supervision tree. + </p> + + <code type="erl"><![CDATA[ +callback_mode() -> + state_functions. + ]]></code> + <p> + Function + <seealso marker="stdlib:gen_statem#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso> + selects the + <seealso marker="#Callback Modes"><c>CallbackMode</c></seealso> + for the callback module, in this case + <seealso marker="stdlib:gen_statem#type-callback_mode"><c>state_functions</c></seealso>. + That is, each state has got its own handler function. + </p> + + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Handling Events" /> + <title>Handling Events</title> + <p>The function notifying the code lock about a button event is + implemented using + <seealso marker="stdlib:gen_statem#cast/2"><c>gen_statem:cast/2</c></seealso>: + </p> + <code type="erl"><![CDATA[ +button(Digit) -> + gen_statem:cast(?NAME, {button,Digit}). + ]]></code> + <p> + The first argument is the name of the <c>gen_statem</c> and must + agree with the name used to start it. So, we use the + same macro <c>?NAME</c> as when starting. + <c>{button,Digit}</c> is the event content. + </p> + <p> + The event is made into a message and sent to the <c>gen_statem</c>. + When the event is received, the <c>gen_statem</c> calls + <c>StateName(cast, Event, Data)</c>, which is expected to + return a tuple <c>{next_state, NewStateName, NewData}</c>, + or <c>{next_state, NewStateName, NewData, Actions}</c>. + <c>StateName</c> is the name of the current state and + <c>NewStateName</c> is the name of the next state to go to. + <c>NewData</c> is a new value for the server data of + the <c>gen_statem</c>, and <c>Actions</c> is a list of + actions on the <c>gen_statem</c> engine. + </p> + <code type="erl"><![CDATA[ +locked( + cast, {button,Digit}, + #{code := Code, remaining := Remaining} = Data) -> + case Remaining of + [Digit] -> % Complete + do_unlock(), + {next_state, open, Data#{remaining := Code}, + [{state_timeout,10000,lock}]}; + [Digit|Rest] -> % Incomplete + {next_state, locked, Data#{remaining := Rest}}; + [_|_] -> % Wrong + {next_state, locked, Data#{remaining := Code}} + end. + +open(state_timeout, lock, Data) -> + do_lock(), + {next_state, locked, Data}; +open(cast, {button,_}, Data) -> + {next_state, open, Data}. + ]]></code> + <p> + If the door is locked and a button is pressed, the pressed + button is compared with the next correct button. + Depending on the result, the door is either unlocked + and the <c>gen_statem</c> goes to state <c>open</c>, + or the door remains in state <c>locked</c>. + </p> + <p> + If the pressed button is incorrect, the server data + restarts from the start of the code sequence. + </p> + <p> + If the whole code is correct, the server changes states + to <c>open</c>. + </p> + <p> + In state <c>open</c>, a button event is ignored + by staying in the same state. This can also be done + by returning <c>{keep_state, Data}</c> or in this case + since <c>Data</c> unchanged even by returning + <c>keep_state_and_data</c>. + </p> + </section> + + <section> + <marker id="State Time-Outs" /> + <title>State Time-Outs</title> + <p> + When a correct code has been given, the door is unlocked and + the following tuple is returned from <c>locked/2</c>: + </p> + <code type="erl"><![CDATA[ +{next_state, open, Data#{remaining := Code}, + [{state_timeout,10000,lock}]}; + ]]></code> + <p> + 10,000 is a time-out value in milliseconds. + After this time (10 seconds), a time-out occurs. + Then, <c>StateName(state_timeout, lock, Data)</c> is called. + The time-out occurs when the door has been in state <c>open</c> + for 10 seconds. After that the door is locked again: + </p> + <code type="erl"><![CDATA[ +open(state_timeout, lock, Data) -> + do_lock(), + {next_state, locked, Data}; + ]]></code> + <p> + The timer for a state time-out is automatically cancelled + when the state machine changes states. You can restart + a state time-out by setting it to a new time, which cancels + the running timer and starts a new. This implies that + you can cancel a state time-out by restarting it with + time <c>infinity</c>. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="All State Events" /> + <title>All State Events</title> + <p> + Sometimes events can arrive in any state of the <c>gen_statem</c>. + It is convenient to handle these in a common state handler function + that all state functions call for events not specific to the state. + </p> + <p> + Consider a <c>code_length/0</c> function that returns + the length of the correct code + (that should not be sensitive to reveal). + We dispatch all events that are not state-specific + to the common function <c>handle_event/3</c>: + </p> + <code type="erl"><![CDATA[ +... +-export([button/1,code_length/0]). +... + +code_length() -> + gen_statem:call(?NAME, code_length). + +... +locked(...) -> ... ; +locked(EventType, EventContent, Data) -> + handle_event(EventType, EventContent, Data). + +... +open(...) -> ... ; +open(EventType, EventContent, Data) -> + handle_event(EventType, EventContent, Data). + +handle_event({call,From}, code_length, #{code := Code} = Data) -> + {keep_state, Data, [{reply,From,length(Code)}]}. + ]]></code> + <p> + This example uses + <seealso marker="stdlib:gen_statem#call/2"><c>gen_statem:call/2</c></seealso>, + which waits for a reply from the server. + The reply is sent with a <c>{reply,From,Reply}</c> tuple + in an action list in the <c>{keep_state, ...}</c> tuple + that retains the current state. This return form is convenient + when you want to stay in the current state but do not know or + care about what it is. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="One Event Handler" /> + <title>One Event Handler</title> + <p> + If mode <c>handle_event_function</c> is used, + all events are handled in + <seealso marker="stdlib:gen_statem#Module:handle_event/4"><c>Module:handle_event/4</c></seealso> + and we can (but do not have to) use an event-centered approach + where we first branch depending on event + and then depending on state: + </p> + <code type="erl"><![CDATA[ +... +-export([handle_event/4]). + +... +callback_mode() -> + handle_event_function. + +handle_event(cast, {button,Digit}, State, #{code := Code} = Data) -> + case State of + locked -> + case maps:get(remaining, Data) of + [Digit] -> % Complete + do_unlock(), + {next_state, open, Data#{remaining := Code}, + [{state_timeout,10000,lock}}; + [Digit|Rest] -> % Incomplete + {keep_state, Data#{remaining := Rest}}; + [_|_] -> % Wrong + {keep_state, Data#{remaining := Code}} + end; + open -> + keep_state_and_data + end; +handle_event(state_timeout, lock, open, Data) -> + do_lock(), + {next_state, locked, Data}. + +... + ]]></code> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Stopping" /> + <title>Stopping</title> + + <section> + <marker id="In a Supervision Tree" /> + <title>In a Supervision Tree</title> + <p> + If the <c>gen_statem</c> is part of a supervision tree, + no stop function is needed. + The <c>gen_statem</c> is automatically terminated by its supervisor. + Exactly how this is done is defined by a + <seealso marker="sup_princ#shutdown">shutdown strategy</seealso> + set in the supervisor. + </p> + <p> + If it is necessary to clean up before termination, the shutdown + strategy must be a time-out value and the <c>gen_statem</c> must + in function <c>init/1</c> set itself to trap exit signals + by calling + <seealso marker="erts:erlang#process_flag/2"><c>process_flag(trap_exit, true)</c></seealso>: + </p> + <code type="erl"><![CDATA[ +init(Args) -> + process_flag(trap_exit, true), + do_lock(), + ... + ]]></code> + <p> + When ordered to shut down, the <c>gen_statem</c> then calls + callback function <c>terminate(shutdown, State, Data)</c>. + </p> + <p> + In this example, function <c>terminate/3</c> + locks the door if it is open, so we do not accidentally leave the door + open when the supervision tree terminates: + </p> + <code type="erl"><![CDATA[ +terminate(_Reason, State, _Data) -> + State =/= locked andalso do_lock(), + ok. + ]]></code> + </section> + + <section> + <marker id="Standalone gen_statem" /> + <title>Standalone gen_statem</title> + <p> + If the <c>gen_statem</c> is not part of a supervision tree, + it can be stopped using + <seealso marker="stdlib:gen_statem#stop/1"><c>gen_statem:stop</c></seealso>, + preferably through an API function: + </p> + <code type="erl"><![CDATA[ +... +-export([start_link/1,stop/0]). + +... +stop() -> + gen_statem:stop(?NAME). + ]]></code> + <p> + This makes the <c>gen_statem</c> call callback function + <c>terminate/3</c> just like for a supervised server + and waits for the process to terminate. + </p> + </section> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Event Time-Outs" /> + <title>Event Time-Outs</title> + <p> + A timeout feature inherited from <c>gen_statem</c>'s predecessor + <seealso marker="stdlib:gen_fsm"><c>gen_fsm</c></seealso>, + is an event time-out, that is, + if an event arrives the timer is cancelled. + You get either an event or a time-out, but not both. + </p> + <p> + It is ordered by the state transition action + <c>{timeout,Time,EventContent}</c>, or just <c>Time</c>, + or even just <c>Time</c> instead of an action list + (the latter is a form inherited from <c>gen_fsm</c>. + </p> + <p> + This type of time-out is useful to for example act on inactivity. + Let us restart the code sequence + if no button is pressed for say 30 seconds: + </p> + <code type="erl"><![CDATA[ +... + +locked( + timeout, _, + #{code := Code, remaining := Remaining} = Data) -> + {next_state, locked, Data#{remaining := Code}}; +locked( + cast, {button,Digit}, + #{code := Code, remaining := Remaining} = Data) -> +... + [Digit|Rest] -> % Incomplete + {next_state, locked, Data#{remaining := Rest}, 30000}; +... + ]]></code> + <p> + Whenever we receive a button event we start an event timeout + of 30 seconds, and if we get an event type <c>timeout</c> + we reset the remaining code sequence. + </p> + <p> + An event timeout is cancelled by any other event so you either + get some other event or the timeout event. It is therefore + not possible nor needed to cancel or restart an event timeout. + Whatever event you act on has already cancelled + the event timeout... + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Erlang Timers" /> + <title>Erlang Timers</title> + <p> + The previous example of state time-outs only work if + the state machine stays in the same state during the + time-out time. And event time-outs only work if no + disturbing unrelated events occur. + </p> + <p> + You may want to start a timer in one state and respond + to the time-out in another, maybe cancel the time-out + without changing states, or perhaps run multiple + time-outs in parallel. All this can be accomplished + with Erlang Timers: + <seealso marker="erts:erlang#start_timer/4"><c>erlang:start_timer3,4</c></seealso>. + </p> + <p> + Here is how to accomplish the state time-out + in the previous example by insted using an Erlang Timer: + </p> + <code type="erl"><![CDATA[ +... +locked( + cast, {button,Digit}, + #{code := Code, remaining := Remaining} = Data) -> + case Remaining of + [Digit] -> + do_unlock(), + Tref = erlang:start_timer(10000, self(), lock), + {next_state, open, Data#{remaining := Code, timer => Tref}}; +... + +open(info, {timeout,Tref,lock}, #{timer := Tref} = Data) -> + do_lock(), + {next_state,locked,maps:remove(timer, Data)}; +open(cast, {button,_}, Data) -> + {keep_state,Data}; +... + ]]></code> + <p> + Removing the <c>timer</c> key from the map when we + change to state <c>locked</c> is not strictly + necessary since we can only get into state <c>open</c> + with an updated <c>timer</c> map value. But it can be nice + to not have outdated values in the state <c>Data</c>! + </p> + <p> + If you need to cancel a timer because of some other event, you can use + <seealso marker="erts:erlang#cancel_timer/2"><c>erlang:cancel_timer(Tref)</c></seealso>. + Note that a time-out message cannot arrive after this, + unless you have postponed it before (see the next section), + so ensure that you do not accidentally postpone such messages. + Also note that a time-out message may have arrived + just before you cancelling it, so you may have to read out + such a message from the process mailbox depending on + the return value from + <seealso marker="erts:erlang#cancel_timer/2"><c>erlang:cancel_timer(Tref)</c></seealso>. + </p> + <p> + Another way to handle a late time-out can be to not cancel it, + but to ignore it if it arrives in a state + where it is known to be late. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Postponing Events" /> + <title>Postponing Events</title> + <p> + If you want to ignore a particular event in the current state + and handle it in a future state, you can postpone the event. + A postponed event is retried after the state has + changed, that is, <c>OldState =/= NewState</c>. + </p> + <p> + Postponing is ordered by the state transition + <seealso marker="stdlib:gen_statem#type-action">action</seealso> + <c>postpone</c>. + </p> + <p> + In this example, instead of ignoring button events + while in the <c>open</c> state, we can postpone them + and they are queued and later handled in the <c>locked</c> state: + </p> + <code type="erl"><![CDATA[ +... +open(cast, {button,_}, Data) -> + {keep_state,Data,[postpone]}; +... + ]]></code> + <p> + Since a postponed event is only retried after a state change, + you have to think about where to keep a state data item. + You can keep it in the server <c>Data</c> + or in the <c>State</c> itself, + for example by having two more or less identical states + to keep a boolean value, or by using a complex state with + <seealso marker="#Callback Modes">callback mode</seealso> + <seealso marker="stdlib:gen_statem#type-callback_mode"><c>handle_event_function</c></seealso>. + If a change in the value changes the set of events that is handled, + then the value should be kept in the State. + Otherwise no postponed events will be retried + since only the server Data changes. + </p> + <p> + This is not important if you do not postpone events. + But if you later decide to start postponing some events, + then the design flaw of not having separate states + when they should be, might become a hard to find bug. + </p> + + <section> + <marker id="Fuzzy State Diagrams" /> + <title>Fuzzy State Diagrams</title> + <p> + It is not uncommon that a state diagram does not specify + how to handle events that are not illustrated + in a particular state in the diagram. + Hopefully this is described in an associated text + or from the context. + </p> + <p> + Possible actions: ignore as in drop the event + (maybe log it) or deal with the event in some other state + as in postpone it. + </p> + </section> + + <section> + <marker id="Selective Receive" /> + <title>Selective Receive</title> + <p> + Erlang's selective receive statement is often used to + describe simple state machine examples in straightforward + Erlang code. The following is a possible implementation of + the first example: + </p> + <code type="erl"><![CDATA[ +-module(code_lock). +-define(NAME, code_lock_1). +-export([start_link/1,button/1]). + +start_link(Code) -> + spawn( + fun () -> + true = register(?NAME, self()), + do_lock(), + locked(Code, Code) + end). + +button(Digit) -> + ?NAME ! {button,Digit}. + +locked(Code, [Digit|Remaining]) -> + receive + {button,Digit} when Remaining =:= [] -> + do_unlock(), + open(Code); + {button,Digit} -> + locked(Code, Remaining); + {button,_} -> + locked(Code, Code) + end. + +open(Code) -> + receive + after 10000 -> + do_lock(), + locked(Code, Code) + end. + +do_lock() -> + io:format("Locked~n", []). +do_unlock() -> + io:format("Open~n", []). + ]]></code> + <p> + The selective receive in this case causes implicitly <c>open</c> + to postpone any events to the <c>locked</c> state. + </p> + <p> + A selective receive cannot be used from a <c>gen_statem</c> + behavior as for any <c>gen_*</c> behavior, + as the receive statement is within the <c>gen_*</c> engine itself. + It must be there because all + <seealso marker="stdlib:sys"><c>sys</c></seealso> + compatible behaviors must respond to system messages and therefore + do that in their engine receive loop, + passing non-system messages to the callback module. + </p> + <p> + The state transition + <seealso marker="stdlib:gen_statem#type-action">action</seealso> + <c>postpone</c> is designed to model + selective receives. A selective receive implicitly postpones + any not received events, but the <c>postpone</c> + state transition action explicitly postpones one received event. + </p> + <p> + Both mechanisms have the same theoretical + time and memory complexity, while the selective receive + language construct has smaller constant factors. + </p> + </section> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="State Entry Actions" /> + <title>State Entry Actions</title> + <p> + Say you have a state machine specification + that uses state entry actions. + Allthough you can code this using self-generated events + (described in the next section), especially if just + one or a few states has got state entry actions, + this is a perfect use case for the built in + <seealso marker="#State Enter Calls">state enter calls</seealso>. + </p> + <p> + You return a list containing <c>state_enter</c> from your + <seealso marker="stdlib:gen_statem#Module:callback_mode/0"><c>callback_mode/0</c></seealso> + function and the <c>gen_statem</c> engine will call your + state callback once with the arguments + <c>(enter, OldState, ...)</c> whenever the state changes. + Then you just need to handle these event-like calls in all states. + </p> + <code type="erl"><![CDATA[ +... +init(Code) -> + process_flag(trap_exit, true), + Data = #{code => Code}, + {ok, locked, Data}. + +callback_mode() -> + [state_functions,state_enter]. + +locked(enter, _OldState, Data) -> + do_lock(), + {keep_state,Data#{remaining => Code}}; +locked( + cast, {button,Digit}, + #{code := Code, remaining := Remaining} = Data) -> + case Remaining of + [Digit] -> + {next_state, open, Data}; +... + +open(enter, _OldState, _Data) -> + do_unlock(), + {keep_state_and_data, [{state_timeout,10000,lock}]}; +open(state_timeout, lock, Data) -> + {next_state, locked, Data}; +... + ]]></code> + <p> + You can repeat the state entry code by returning one of + <c>{repeat_state, ...}</c>, <c>{repeat_state_and_data,_}</c> + or <c>repeat_state_and_data</c> that otherwise behaves + exactly like their <c>keep_state</c> siblings. + See the type + <seealso marker="stdlib:gen_statem#type-state_callback_result"> + <c>state_callback_result()</c> + </seealso> + in the reference manual. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Self-Generated Events" /> + <title>Self-Generated Events</title> + <p> + It can sometimes be beneficial to be able to generate events + to your own state machine. + This can be done with the state transition + <seealso marker="stdlib:gen_statem#type-action">action</seealso> + <c>{next_event,EventType,EventContent}</c>. + </p> + <p> + You can generate events of any existing + <seealso marker="stdlib:gen_statem#type-action">type</seealso>, + but the <c>internal</c> type can only be generated through action + <c>next_event</c>. Hence, it cannot come from an external source, + so you can be certain that an <c>internal</c> event is an event + from your state machine to itself. + </p> + <p> + One example for this is to pre-process incoming data, for example + decrypting chunks or collecting characters up to a line break. + Purists may argue that this should be modelled with a separate + state machine that sends pre-processed events + to the main state machine. + But to decrease overhead the small pre-processing state machine + can be implemented in the common state event handling + of the main state machine using a few state data variables + that then sends the pre-processed events as internal events + to the main state machine. + </p> + <p> + The following example uses an input model where you give the lock + characters with <c>put_chars(Chars)</c> and then call + <c>enter()</c> to finish the input. + </p> + <code type="erl"><![CDATA[ +... +-export(put_chars/1, enter/0). +... +put_chars(Chars) when is_binary(Chars) -> + gen_statem:call(?NAME, {chars,Chars}). + +enter() -> + gen_statem:call(?NAME, enter). + +... + +locked(enter, _OldState, Data) -> + do_lock(), + {keep_state,Data#{remaining => Code, buf => []}}; +... + +handle_event({call,From}, {chars,Chars}, #{buf := Buf} = Data) -> + {keep_state, Data#{buf := [Chars|Buf], + [{reply,From,ok}]}; +handle_event({call,From}, enter, #{buf := Buf} = Data) -> + Chars = unicode:characters_to_binary(lists:reverse(Buf)), + try binary_to_integer(Chars) of + Digit -> + {keep_state, Data#{buf := []}, + [{reply,From,ok}, + {next_event,internal,{button,Chars}}]} + catch + error:badarg -> + {keep_state, Data#{buf := []}, + [{reply,From,{error,not_an_integer}}]} + end; +... + ]]></code> + <p> + If you start this program with <c>code_lock:start([17])</c> + you can unlock with <c>code_lock:put_chars(<<"001">>), + code_lock:put_chars(<<"7">>), code_lock:enter()</c>. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Example Revisited" /> + <title>Example Revisited</title> + <p> + This section includes the example after most of the mentioned + modifications and some more using state enter calls, + which deserves a new state diagram: + </p> + <image file="../design_principles/code_lock_2.png"> + <icaption>Code Lock State Diagram Revisited</icaption> + </image> + <p> + Notice that this state diagram does not specify how to handle + a button event in the state <c>open</c>. So, you need to + read somewhere else that unspecified events + must be ignored as in not consumed but handled in some other state. + Also, the state diagram does not show that the <c>code_length/0</c> + call must be handled in every state. + </p> + + <section> + <marker id="Callback Mode: state_functions" /> + <title>Callback Mode: state_functions</title> + <p> + Using state functions: + </p> + <code type="erl"><![CDATA[ +-module(code_lock). +-behaviour(gen_statem). +-define(NAME, code_lock_2). + +-export([start_link/1,stop/0]). +-export([button/1,code_length/0]). +-export([init/1,callback_mode/0,terminate/3,code_change/4]). +-export([locked/3,open/3]). + +start_link(Code) -> + gen_statem:start_link({local,?NAME}, ?MODULE, Code, []). +stop() -> + gen_statem:stop(?NAME). + +button(Digit) -> + gen_statem:cast(?NAME, {button,Digit}). +code_length() -> + gen_statem:call(?NAME, code_length). + +init(Code) -> + process_flag(trap_exit, true), + Data = #{code => Code}, + {ok, locked, Data}. + +callback_mode() -> + [state_functions,state_enter]. + +locked(enter, _OldState, #{code := Code} = Data) -> + do_lock(), + {keep_state, Data#{remaining => Code}}; +locked( + timeout, _, + #{code := Code, remaining := Remaining} = Data) -> + {keep_state, Data#{remaining := Code}}; +locked( + cast, {button,Digit}, + #{code := Code, remaining := Remaining} = Data) -> + case Remaining of + [Digit] -> % Complete + {next_state, open, Data}; + [Digit|Rest] -> % Incomplete + {keep_state, Data#{remaining := Rest}, 30000}; + [_|_] -> % Wrong + {keep_state, Data#{remaining := Code}} + end; +locked(EventType, EventContent, Data) -> + handle_event(EventType, EventContent, Data). + +open(enter, _OldState, _Data) -> + do_unlock(), + {keep_state_and_data, [{state_timeout,10000,lock}]}; +open(state_timeout, lock, Data) -> + {next_state, locked, Data}; +open(cast, {button,_}, _) -> + {keep_state_and_data, [postpone]}; +open(EventType, EventContent, Data) -> + handle_event(EventType, EventContent, Data). + +handle_event({call,From}, code_length, #{code := Code}) -> + {keep_state_and_data, [{reply,From,length(Code)}]}. + +do_lock() -> + io:format("Locked~n", []). +do_unlock() -> + io:format("Open~n", []). + +terminate(_Reason, State, _Data) -> + State =/= locked andalso do_lock(), + ok. +code_change(_Vsn, State, Data, _Extra) -> + {ok,State,Data}. + ]]></code> + </section> + + <section> + <marker id="Callback Mode: handle_event_function" /> + <title>Callback Mode: handle_event_function</title> + <p> + This section describes what to change in the example + to use one <c>handle_event/4</c> function. + The previously used approach to first branch depending on event + does not work that well here because of the state enter calls, + so this example first branches depending on state: + </p> + <code type="erl"><![CDATA[ +... +-export([handle_event/4]). + +... +callback_mode() -> + [handle_event_function,state_enter]. + +%% State: locked +handle_event( + enter, _OldState, locked, + #{code := Code} = Data) -> + do_lock(), + {keep_state, Data#{remaining => Code}}; +handle_event( + timeout, _, locked, + #{code := Code, remaining := Remaining} = Data) -> + {keep_state, Data#{remaining := Code}}; +handle_event( + cast, {button,Digit}, locked, + #{code := Code, remaining := Remaining} = Data) -> + case Remaining of + [Digit] -> % Complete + {next_state, open, Data}; + [Digit|Rest] -> % Incomplete + {keep_state, Data#{remaining := Rest}, 30000}; + [_|_] -> % Wrong + {keep_state, Data#{remaining := Code}} + end; +%% +%% State: open +handle_event(enter, _OldState, open, _Data) -> + do_unlock(), + {keep_state_and_data, [{state_timeout,10000,lock}]}; +handle_event(state_timeout, lock, open, Data) -> + {next_state, locked, Data}; +handle_event(cast, {button,_}, open, _) -> + {keep_state_and_data,[postpone]}; +%% +%% Any state +handle_event({call,From}, code_length, _State, #{code := Code}) -> + {keep_state_and_data, [{reply,From,length(Code)}]}. + +... + ]]></code> + </section> + <p> + Notice that postponing buttons from the <c>locked</c> state + to the <c>open</c> state feels like a strange thing to do + for a code lock, but it at least illustrates event postponing. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Filter the State" /> + <title>Filter the State</title> + <p> + The example servers so far in this chapter + print the full internal state in the error log, for example, + when killed by an exit signal or because of an internal error. + This state contains both the code lock code + and which digits that remain to unlock. + </p> + <p> + This state data can be regarded as sensitive, + and maybe not what you want in the error log + because of some unpredictable event. + </p> + <p> + Another reason to filter the state can be + that the state is too large to print, as it fills + the error log with uninteresting details. + </p> + <p> + To avoid this, you can format the internal state + that gets in the error log and gets returned from + <seealso marker="stdlib:sys#get_status/1"><c>sys:get_status/1,2</c></seealso> + by implementing function + <seealso marker="stdlib:gen_statem#Module:format_status/2"><c>Module:format_status/2</c></seealso>, + for example like this: + </p> + <code type="erl"><![CDATA[ +... +-export([init/1,terminate/3,code_change/4,format_status/2]). +... + +format_status(Opt, [_PDict,State,Data]) -> + StateData = + {State, + maps:filter( + fun (code, _) -> false; + (remaining, _) -> false; + (_, _) -> true + end, + Data)}, + case Opt of + terminate -> + StateData; + normal -> + [{data,[{"State",StateData}]}] + end. + ]]></code> + <p> + It is not mandatory to implement a + <seealso marker="stdlib:gen_statem#Module:format_status/2"><c>Module:format_status/2</c></seealso> + function. If you do not, a default implementation is used that + does the same as this example function without filtering + the <c>Data</c> term, that is, <c>StateData = {State,Data}</c>, + in this example containing sensitive information. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Complex State" /> + <title>Complex State</title> + <p> + The callback mode + <seealso marker="stdlib:gen_statem#type-callback_mode"><c>handle_event_function</c></seealso> + enables using a non-atom state as described in section + <seealso marker="#Callback Modes">Callback Modes</seealso>, + for example, a complex state term like a tuple. + </p> + <p> + One reason to use this is when you have + a state item that affects the event handling, + in particular in combination with postponing events. + We complicate the previous example + by introducing a configurable lock button + (this is the state item in question), + which in the <c>open</c> state immediately locks the door, + and an API function <c>set_lock_button/1</c> to set the lock button. + </p> + <p> + Suppose now that we call <c>set_lock_button</c> + while the door is open, + and have already postponed a button event + that until now was not the lock button. + The sensible thing can be to say that + the button was pressed too early so it is + not to be recognized as the lock button. + However, then it can be surprising that a button event + that now is the lock button event arrives (as retried postponed) + immediately after the state transits to <c>locked</c>. + </p> + <p> + So we make the <c>button/1</c> function synchronous + by using + <seealso marker="stdlib:gen_statem#call/2"><c>gen_statem:call</c></seealso> + and still postpone its events in the <c>open</c> state. + Then a call to <c>button/1</c> during the <c>open</c> + state does not return until the state transits to <c>locked</c>, + as it is there the event is handled and the reply is sent. + </p> + <p> + If a process now calls <c>set_lock_button/1</c> + to change the lock button while another process + hangs in <c>button/1</c> with the new lock button, + it can be expected that the hanging lock button call + immediately takes effect and locks the lock. + Therefore, we make the current lock button a part of the state, + so that when we change the lock button, the state changes + and all postponed events are retried. + </p> + <p> + We define the state as <c>{StateName,LockButton}</c>, + where <c>StateName</c> is as before + and <c>LockButton</c> is the current lock button: + </p> + <code type="erl"><![CDATA[ +-module(code_lock). +-behaviour(gen_statem). +-define(NAME, code_lock_3). + +-export([start_link/2,stop/0]). +-export([button/1,code_length/0,set_lock_button/1]). +-export([init/1,callback_mode/0,terminate/3,code_change/4,format_status/2]). +-export([handle_event/4]). + +start_link(Code, LockButton) -> + gen_statem:start_link( + {local,?NAME}, ?MODULE, {Code,LockButton}, []). +stop() -> + gen_statem:stop(?NAME). + +button(Digit) -> + gen_statem:call(?NAME, {button,Digit}). +code_length() -> + gen_statem:call(?NAME, code_length). +set_lock_button(LockButton) -> + gen_statem:call(?NAME, {set_lock_button,LockButton}). + +init({Code,LockButton}) -> + process_flag(trap_exit, true), + Data = #{code => Code, remaining => undefined}, + {ok, {locked,LockButton}, Data}. + +callback_mode() -> + [handle_event_function,state_enter]. + +handle_event( + {call,From}, {set_lock_button,NewLockButton}, + {StateName,OldLockButton}, Data) -> + {next_state, {StateName,NewLockButton}, Data, + [{reply,From,OldLockButton}]}; +handle_event( + {call,From}, code_length, + {_StateName,_LockButton}, #{code := Code}) -> + {keep_state_and_data, + [{reply,From,length(Code)}]}; +%% +%% State: locked +handle_event( + EventType, EventContent, + {locked,LockButton}, #{code := Code, remaining := Remaining} = Data) -> + case {EventType, EventContent} of + {enter, _OldState} -> + do_lock(), + {keep_state, Data#{remaining := Code}}; + {timeout, _} -> + {keep_state, Data#{remaining := Code}}; + {{call,From}, {button,Digit}} -> + case Remaining of + [Digit] -> % Complete + {next_state, {open,LockButton}, Data, + [{reply,From,ok}]}; + [Digit|Rest] -> % Incomplete + {keep_state, Data#{remaining := Rest, 30000}, + [{reply,From,ok}]}; + [_|_] -> % Wrong + {keep_state, Data#{remaining := Code}, + [{reply,From,ok}]} + end + end; +%% +%% State: open +handle_event( + EventType, EventContent, + {open,LockButton}, Data) -> + case {EventType, EventContent} of + {enter, _OldState} -> + do_unlock(), + {keep_state_and_data, [{state_timeout,10000,lock}]}; + {state_timeout, lock} -> + {next_state, {locked,LockButton}, Data}; + {{call,From}, {button,Digit}} -> + if + Digit =:= LockButton -> + {next_state, {locked,LockButton}, Data, + [{reply,From,locked}]); + true -> + {keep_state_and_data, + [postpone]} + end + end. + +do_lock() -> + io:format("Locked~n", []). +do_unlock() -> + io:format("Open~n", []). + +terminate(_Reason, State, _Data) -> + State =/= locked andalso do_lock(), + ok. +code_change(_Vsn, State, Data, _Extra) -> + {ok,State,Data}. +format_status(Opt, [_PDict,State,Data]) -> + StateData = + {State, + maps:filter( + fun (code, _) -> false; + (remaining, _) -> false; + (_, _) -> true + end, + Data)}, + case Opt of + terminate -> + StateData; + normal -> + [{data,[{"State",StateData}]}] + end. + ]]></code> + <p> + It can be an ill-fitting model for a physical code lock + that the <c>button/1</c> call can hang until the lock + is locked. But for an API in general it is not that strange. + </p> + </section> + +<!-- =================================================================== --> + + <section> + <marker id="Hibernation" /> + <title>Hibernation</title> + <p> + If you have many servers in one node + and they have some state(s) in their lifetime in which + the servers can be expected to idle for a while, + and the amount of heap memory all these servers need + is a problem, then the memory footprint of a server + can be mimimized by hibernating it through + <seealso marker="stdlib:proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>. + </p> + <note> + <p> + It is rather costly to hibernate a process; see + <seealso marker="erts:erlang#hibernate/3"><c>erlang:hibernate/3</c></seealso>. + It is not something you want to do after every event. + </p> + </note> + <p> + We can in this example hibernate in the <c>{open,_}</c> state, + because what normally occurs in that state is that + the state time-out after a while + triggers a transition to <c>{locked,_}</c>: + </p> + <code type="erl"><![CDATA[ +... +%% State: open +handle_event( + EventType, EventContent, + {open,LockButton}, Data) -> + case {EventType, EventContent} of + {enter, _OldState} -> + do_unlock(), + {keep_state_and_data, + [{state_timeout,10000,lock},hibernate]}; +... + ]]></code> + <p> + The atom + <seealso marker="stdlib:gen_statem#type-hibernate"><c>hibernate</c></seealso> + in the action list on the last line + when entering the <c>{open,_}</c> state is the only change. + If any event arrives in the <c>{open,_},</c> state, we + do not bother to rehibernate, so the server stays + awake after any event. + </p> + <p> + To change that we would need to insert + action <c>hibernate</c> in more places. + For example, for the state-independent <c>set_lock_button</c> + and <c>code_length</c> operations that then would have to + be aware of using <c>hibernate</c> while in the + <c>{open,_}</c> state, which would clutter the code. + </p> + <p> + Another not uncommon scenario is to use the event time-out + to triger hibernation after a certain time of inactivity. + </p> + <p> + This server probably does not use + heap memory worth hibernating for. + To gain anything from hibernation, your server would + have to produce some garbage during callback execution, + for which this example server can serve as a bad example. + </p> + </section> + +</chapter> diff --git a/system/doc/design_principles/sup_princ.xml b/system/doc/design_principles/sup_princ.xml index 5e2f6ba9cb..0a24e97950 100644 --- a/system/doc/design_principles/sup_princ.xml +++ b/system/doc/design_principles/sup_princ.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2014</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -80,8 +80,8 @@ init(_Args) -> </section> <section> - <title>Supervisor Flags</title> <marker id="flags"/> + <title>Supervisor Flags</title> <p>This is the type definition for the supervisor flags:</p> <code type="none"><![CDATA[ sup_flags() = #{strategy => strategy(), % optional @@ -106,9 +106,8 @@ sup_flags() = #{strategy => strategy(), % optional </section> <section> - <marker id="strategy"></marker> + <marker id="strategy"/> <title>Restart Strategy</title> - <p> The restart strategy is specified by the <c>strategy</c> key in the supervisor flags map returned by the callback function <c>init</c>:</p> @@ -213,6 +212,7 @@ child_spec() = #{id => child_id(), % mandatory <item><c>supervisor:start_link</c></item> <item><c>gen_server:start_link</c></item> <item><c>gen_fsm:start_link</c></item> + <item><c>gen_statem:start_link</c></item> <item><c>gen_event:start_link</c></item> <item>A function compliant with these functions. For details, see the <c>supervisor(3)</c> manual page.</item> @@ -229,7 +229,7 @@ child_spec() = #{id => child_id(), % mandatory is <c>rest_for_one</c> or <c>one_for_all</c> and a sibling death causes the temporary process to be terminated).</item> <item>A <c>transient</c> child process is restarted only if it - terminates abnormally, that is, with another exit reason than + terminates abnormally, that is, with an exit reason other than <c>normal</c>, <c>shutdown</c>, or <c>{shutdown,Term}</c>.</item> </list> <p>The <c>restart</c> key is optional. If it is not given, the @@ -276,7 +276,8 @@ child_spec() = #{id => child_id(), % mandatory <p><c>modules</c> are to be a list with one element <c>[Module]</c>, where <c>Module</c> is the name of the callback module, if the child process is a supervisor, - gen_server or gen_fsm. If the child process is a gen_event, + gen_server, gen_fsm or gen_statem. + If the child process is a gen_event, the value shall be <c>dynamic</c>.</p> <p>This information is used by the release handler during upgrades and downgrades, see @@ -400,8 +401,8 @@ supervisor:delete_child(Sup, Id)</code> restarts.</p> </section> - <marker id="simple"/> <section> + <marker id="simple"/> <title>Simplified one_for_one Supervisors</title> <p>A supervisor with restart strategy <c>simple_one_for_one</c> is a simplified <c>one_for_one</c> supervisor, where all child diff --git a/system/doc/design_principles/xmlfiles.mk b/system/doc/design_principles/xmlfiles.mk index 3032ac3ab9..e476255d62 100644 --- a/system/doc/design_principles/xmlfiles.mk +++ b/system/doc/design_principles/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009. 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. @@ -25,6 +25,7 @@ DESIGN_PRINCIPLES_CHAPTER_FILES = \ distributed_applications.xml \ events.xml \ fsm.xml \ + statem.xml \ gen_server_concepts.xml \ included_applications.xml \ release_handling.xml \ diff --git a/system/doc/efficiency_guide/Makefile b/system/doc/efficiency_guide/Makefile index 87997b6e41..ce93762ced 100644 --- a/system/doc/efficiency_guide/Makefile +++ b/system/doc/efficiency_guide/Makefile @@ -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/system/doc/efficiency_guide/advanced.xml b/system/doc/efficiency_guide/advanced.xml index d4e47f4f10..e1760d0ded 100644 --- a/system/doc/efficiency_guide/advanced.xml +++ b/system/doc/efficiency_guide/advanced.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2001</year><year>2013</year> + <year>2001</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -35,8 +35,7 @@ how much memory different data types and operations require. It is implementation-dependent how much memory the Erlang data types and other items consume, but the following table shows some figures for - the <c>erts-5.2</c> system in R9B. There have been no significant - changes in R13.</p> + the <c>erts-8.0</c> system in OTP 19.0.</p> <p>The unit of measurement is memory words. There exists both a 32-bit and a 64-bit implementation. A word is therefore 4 bytes or @@ -87,6 +86,19 @@ <cell>2 words + the size of each element.</cell> </row> <row> + <cell>Small Map</cell> + <cell>5 words + the size of all keys and values.</cell> + </row> + <row> + <cell>Large Map (> 32 keys)</cell> + <cell> + <c>N</c> x <c>F</c> words + the size of all keys and values.<br></br> + <c>N</c> is the number of keys in the Map.<br></br> + <c>F</c> is a sparsity factor that can vary between 1.6 and 1.8 + due to the probabilistic nature of the internal HAMT data structure. + </cell> + </row> + <row> <cell>Pid</cell> <cell>1 word for a process identifier from the current local node + 5 words for a process identifier from another node.<br></br> @@ -122,7 +134,7 @@ </row> <row> <cell>Erlang process</cell> - <cell>327 words when spawned, including a heap of 233 words.</cell> + <cell>338 words when spawned, including a heap of 233 words.</cell> </row> <tcaption>Memory Size of Different Data Types</tcaption> </table> @@ -144,7 +156,7 @@ <seealso marker="erts:erl#max_processes"><c>+P</c></seealso> command-line flag in the <seealso marker="erts:erl"><c>erl(1)</c></seealso> - manual page in <c>erts</c>.</cell> + manual page in ERTS.</cell> </row> <row> <cell>Known nodes</cell> @@ -224,7 +236,7 @@ <seealso marker="erts:erl#max_ports"><c>+Q</c></seealso> command-line flag in the <seealso marker="erts:erl"><c>erl(1)</c></seealso> manual page - in <c>erts</c>.</cell> + in ERTS.</cell> </row> <row> <cell><marker id="files_sockets"></marker>Open files and diff --git a/system/doc/efficiency_guide/appendix.xml b/system/doc/efficiency_guide/appendix.xml index 1e2e906515..225c8c4e2f 100644 --- a/system/doc/efficiency_guide/appendix.xml +++ b/system/doc/efficiency_guide/appendix.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2002</year> - <year>2013</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/system/doc/efficiency_guide/binaryhandling.xml b/system/doc/efficiency_guide/binaryhandling.xml index 0964b759d8..0295d18644 100644 --- a/system/doc/efficiency_guide/binaryhandling.xml +++ b/system/doc/efficiency_guide/binaryhandling.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2007</year> - <year>2014</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/system/doc/efficiency_guide/book.xml b/system/doc/efficiency_guide/book.xml index 76f0ad24d3..e3d6fd5fc2 100644 --- a/system/doc/efficiency_guide/book.xml +++ b/system/doc/efficiency_guide/book.xml @@ -4,7 +4,7 @@ <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <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/system/doc/efficiency_guide/commoncaveats.xml b/system/doc/efficiency_guide/commoncaveats.xml index c1d71e745a..ecfeff0349 100644 --- a/system/doc/efficiency_guide/commoncaveats.xml +++ b/system/doc/efficiency_guide/commoncaveats.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/efficiency_guide/drivers.xml b/system/doc/efficiency_guide/drivers.xml index 202551ab8e..c99701eeba 100644 --- a/system/doc/efficiency_guide/drivers.xml +++ b/system/doc/efficiency_guide/drivers.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2009</year><year>2013</year> + <year>2009</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/system/doc/efficiency_guide/functions.xml b/system/doc/efficiency_guide/functions.xml index 9616df554e..4a8248e65c 100644 --- a/system/doc/efficiency_guide/functions.xml +++ b/system/doc/efficiency_guide/functions.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/efficiency_guide/introduction.xml b/system/doc/efficiency_guide/introduction.xml index 121ce3af21..ca4a41c798 100644 --- a/system/doc/efficiency_guide/introduction.xml +++ b/system/doc/efficiency_guide/introduction.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/efficiency_guide/listhandling.xml b/system/doc/efficiency_guide/listhandling.xml index c7b5cf9a9a..2ebc877820 100644 --- a/system/doc/efficiency_guide/listhandling.xml +++ b/system/doc/efficiency_guide/listhandling.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/efficiency_guide/myths.xml b/system/doc/efficiency_guide/myths.xml index 651d909834..5d3ad78b23 100644 --- a/system/doc/efficiency_guide/myths.xml +++ b/system/doc/efficiency_guide/myths.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/system/doc/efficiency_guide/part.xml b/system/doc/efficiency_guide/part.xml index 2862058bf2..6e10a0c031 100644 --- a/system/doc/efficiency_guide/part.xml +++ b/system/doc/efficiency_guide/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <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/system/doc/efficiency_guide/processes.xml b/system/doc/efficiency_guide/processes.xml index 2d486ef7ff..f2d9712f51 100644 --- a/system/doc/efficiency_guide/processes.xml +++ b/system/doc/efficiency_guide/processes.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/efficiency_guide/profiling.xml b/system/doc/efficiency_guide/profiling.xml index 4fbec927f4..bf50a03fa6 100644 --- a/system/doc/efficiency_guide/profiling.xml +++ b/system/doc/efficiency_guide/profiling.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2001</year><year>2013</year> + <year>2001</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -128,7 +128,7 @@ performance impact. Using <c>fprof</c> is just a matter of calling a few library functions, see the <seealso marker="tools:fprof">fprof</seealso> manual page in - <c>tools</c> .<c>fprof</c> was introduced in R8.</p> + Tools .<c>fprof</c> was introduced in R8.</p> </section> <section> @@ -138,7 +138,7 @@ and in which function calls this time has been spent. Time is shown as percentage of total time and absolute time. For more information, see the <seealso marker="tools:eprof">eprof</seealso> - manual page in <c>tools</c>.</p> + manual page in Tools.</p> </section> <section> @@ -152,7 +152,7 @@ optimization. Using <c>cover</c> is just a matter of calling a few library functions, see the <seealso marker="tools:cover">cover</seealso> manual page in - <c>tools</c>.</p> + Tools.</p> </section> <section> @@ -165,7 +165,7 @@ any modules to profile (compared with <c>cover</c>). For more information, see the <seealso marker="tools:cprof">cprof</seealso> manual page in - <c>tools</c>.</p> + Tools.</p> </section> <section> diff --git a/system/doc/efficiency_guide/tablesDatabases.xml b/system/doc/efficiency_guide/tablesDatabases.xml index 865c46bc33..3f77151e55 100644 --- a/system/doc/efficiency_guide/tablesDatabases.xml +++ b/system/doc/efficiency_guide/tablesDatabases.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/efficiency_guide/xmlfiles.mk b/system/doc/efficiency_guide/xmlfiles.mk index e3373d545a..88df9417f5 100644 --- a/system/doc/efficiency_guide/xmlfiles.mk +++ b/system/doc/efficiency_guide/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009. 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/system/doc/embedded/Makefile b/system/doc/embedded/Makefile index c09816564c..598ed280e5 100644 --- a/system/doc/embedded/Makefile +++ b/system/doc/embedded/Makefile @@ -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/system/doc/embedded/book.xml b/system/doc/embedded/book.xml index 5a414152d0..7737da7d2e 100644 --- a/system/doc/embedded/book.xml +++ b/system/doc/embedded/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/system/doc/embedded/embedded_nt.xml b/system/doc/embedded/embedded_nt.xml index b35a5edf36..8e05100585 100644 --- a/system/doc/embedded/embedded_nt.xml +++ b/system/doc/embedded/embedded_nt.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -62,7 +62,7 @@ <p>For Windows NT running on standard PCs with ISA and/or PCI bus, an extension card with a hardware watchdog can be installed.</p> <p>For more information, see the <c>heart(3)</c> manual page in - <c>kernel</c>.</p> + Kernel.</p> </section> </section> @@ -72,7 +72,7 @@ to install the Erlang process as a Windows system service. This service can start after Windows NT has booted.</p> <p>For more information, see the <c>erlsrv</c> manual page - in <c>erts</c>.</p> + in ERTS.</p> </section> </chapter> diff --git a/system/doc/embedded/embedded_solaris.xml b/system/doc/embedded/embedded_solaris.xml index ade5ad344e..eaa334fb39 100644 --- a/system/doc/embedded/embedded_solaris.xml +++ b/system/doc/embedded/embedded_solaris.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -190,7 +190,7 @@ esac</pre> the onboard hardware watchdog can be activated, provided a VME bus driver is added to the operating system (see also Installation Problems).</p> - <p>See also the <c>heart(3)</c> manual page in <c>kernel</c>.</p> + <p>See also the <c>heart(3)</c> manual page in Kernel.</p> </section> <section> @@ -206,7 +206,7 @@ esac</pre> <pre> chown 0 /usr/sbin/reboot chmod 4755 /usr/sbin/reboot</pre> - <p>See also the <c>heart(3)</c> manual page in <c>kernel</c>.</p> + <p>See also the <c>heart(3)</c> manual page in Kernel.</p> </section> <section> @@ -413,8 +413,8 @@ chown root mod_syslog]]></code> <section> <title>Related Documents</title> <p>See the <c>os_mon(3)</c> application, - the <c>application(3)</c> manual page in <c>kernel</c>, - and the <c>erl(1)</c> manual page in <c>erts</c>.</p> + the <c>application(3)</c> manual page in Kernel, + and the <c>erl(1)</c> manual page in ERTS.</p> </section> </section> @@ -474,7 +474,7 @@ chown root mod_syslog]]></code> default, it must be called <c>start</c> and reside in <c><![CDATA[<ERL_INSTALL_DIR>/bin]]></c>. Another start program can be used, by using configuration parameter - <c>start_prg</c> in application <c>sasl</c>.</p> + <c>start_prg</c> in application SASL.</p> <p>The start program must call <c>run_erl</c> as shown below. It must also take an optional parameter, which defaults to <c><![CDATA[<ERL_INSTALL_DIR>/releases/start_erl.data]]></c>.</p> @@ -484,7 +484,7 @@ chown root mod_syslog]]></code> <p>The <c><![CDATA[<RELDIR>]]></c> directory is where new release packets are installed, and where the release handler keeps information about releases. For more information, see the - <c>release_handler(3)</c> manual page in <c>sasl</c>.</p> + <c>release_handler(3)</c> manual page in SASL.</p> <p>The following script illustrates the default behaviour of the program:</p> <code type="none"><![CDATA[ @@ -624,7 +624,7 @@ export RELDIR exec $BINDIR/erlexec -boot $RELDIR/$VSN/start -config $RELDIR/$VSN/sys $*</code> <p>If a diskless and/or read-only client node with the - <c>sasl</c> configuration parameter <c>static_emulator</c> set + SASL configuration parameter <c>static_emulator</c> set to <c>true</c> is about to start, the <c>-boot</c> and <c>-config</c> flags must be changed.</p> <p>As such a client cannot diff --git a/system/doc/embedded/intro.xml b/system/doc/embedded/intro.xml index 7fea2eeb82..2b9d35d24c 100644 --- a/system/doc/embedded/intro.xml +++ b/system/doc/embedded/intro.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1997</year> - <year>2013</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/system/doc/embedded/part.xml b/system/doc/embedded/part.xml index 7bac643be7..d359a888e7 100644 --- a/system/doc/embedded/part.xml +++ b/system/doc/embedded/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <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/system/doc/embedded/starting.xml b/system/doc/embedded/starting.xml index f9454f1021..11bf9b412a 100644 --- a/system/doc/embedded/starting.xml +++ b/system/doc/embedded/starting.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -69,7 +69,7 @@ default, it must be called <c>start</c> and reside in <c><![CDATA[<ERL_INSTALL_DIR>/bin]]></c>. Another start program can be used, by using the configuration parameter <c>start_prg</c> in - the application <c>sasl</c>.</p> + application SASL.</p> <p>The start program must call <c>run_erl</c> as shown below. It must also take an optional parameter which defaults to <c><![CDATA[<ERL_INSTALL_DIR>/bin/start_erl.data]]></c>. @@ -80,8 +80,8 @@ </p> <p>The <c><![CDATA[<RELDIR>]]></c> directory is where new release packets are installed, and where the release handler keeps information - about releases. See <c>release_handler(3)</c> in the - application <c>sasl</c> for further information. + about releases. See <c>release_handler(3)</c> in + application SASL for further information. </p> <p>The following script illustrates the default behaviour of the program. @@ -228,7 +228,7 @@ export PROGNAME export RELDIR exec $BINDIR/erlexec -boot $RELDIR/$VSN/start -config $RELDIR/$VSN/sys $* </code> - <p>If a diskless and/or read-only client node with the <c>sasl</c> + <p>If a diskless and/or read-only client node with the SASL configuration parameter <c>static_emulator</c> set to <c>true</c> is about to start the <c>-boot</c> and <c>-config</c> flags must be changed. As such a client can not read a new <c>start_erl.data</c> diff --git a/system/doc/embedded/target.xml b/system/doc/embedded/target.xml index 20ef6b0fc6..754269aa2f 100644 --- a/system/doc/embedded/target.xml +++ b/system/doc/embedded/target.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/embedded/vme_problems.xml b/system/doc/embedded/vme_problems.xml index 54618935cd..ac276ce9d3 100644 --- a/system/doc/embedded/vme_problems.xml +++ b/system/doc/embedded/vme_problems.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1997</year> - <year>2013</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/system/doc/embedded/xmlfiles.mk b/system/doc/embedded/xmlfiles.mk index 4446aa1516..1e0c71c726 100644 --- a/system/doc/embedded/xmlfiles.mk +++ b/system/doc/embedded/xmlfiles.mk @@ -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/system/doc/embedded/xntp.xml b/system/doc/embedded/xntp.xml index 2f4dc9a534..46213c7865 100644 --- a/system/doc/embedded/xntp.xml +++ b/system/doc/embedded/xntp.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1997</year> - <year>2013</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/system/doc/getting_started/Makefile b/system/doc/getting_started/Makefile index 37b6db3207..5283d53e1c 100644 --- a/system/doc/getting_started/Makefile +++ b/system/doc/getting_started/Makefile @@ -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/system/doc/getting_started/book.xml b/system/doc/getting_started/book.xml index 8dfca19480..1d92105429 100644 --- a/system/doc/getting_started/book.xml +++ b/system/doc/getting_started/book.xml @@ -4,7 +4,7 @@ <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <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/system/doc/getting_started/conc_prog.xml b/system/doc/getting_started/conc_prog.xml index 9f13ee4802..f3136898ad 100644 --- a/system/doc/getting_started/conc_prog.xml +++ b/system/doc/getting_started/conc_prog.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/getting_started/intro.xml b/system/doc/getting_started/intro.xml index 6ac4f912fe..afae4e8c18 100644 --- a/system/doc/getting_started/intro.xml +++ b/system/doc/getting_started/intro.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/getting_started/part.xml b/system/doc/getting_started/part.xml index 4b902f4c63..71e551a404 100644 --- a/system/doc/getting_started/part.xml +++ b/system/doc/getting_started/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <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/system/doc/getting_started/records_macros.xml b/system/doc/getting_started/records_macros.xml index dd2441b64e..3fcdb10088 100644 --- a/system/doc/getting_started/records_macros.xml +++ b/system/doc/getting_started/records_macros.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/getting_started/robustness.xml b/system/doc/getting_started/robustness.xml index abd5892b80..6932f0ca0f 100644 --- a/system/doc/getting_started/robustness.xml +++ b/system/doc/getting_started/robustness.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/getting_started/seq_prog.xml b/system/doc/getting_started/seq_prog.xml index 5698405ed2..6b7e1cd24f 100644 --- a/system/doc/getting_started/seq_prog.xml +++ b/system/doc/getting_started/seq_prog.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/getting_started/xmlfiles.mk b/system/doc/getting_started/xmlfiles.mk index 892db0e8de..d5a41121d6 100644 --- a/system/doc/getting_started/xmlfiles.mk +++ b/system/doc/getting_started/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009. 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/system/doc/installation_guide/Makefile b/system/doc/installation_guide/Makefile index 5d2997b188..29edd10501 100644 --- a/system/doc/installation_guide/Makefile +++ b/system/doc/installation_guide/Makefile @@ -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/system/doc/installation_guide/book.xml b/system/doc/installation_guide/book.xml index 92a64345c0..a7686252c6 100644 --- a/system/doc/installation_guide/book.xml +++ b/system/doc/installation_guide/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/system/doc/installation_guide/install-binary.xml b/system/doc/installation_guide/install-binary.xml index 43f5a57077..b070c02633 100644 --- a/system/doc/installation_guide/install-binary.xml +++ b/system/doc/installation_guide/install-binary.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2000</year><year>2014</year> + <year>2000</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/system/doc/installation_guide/part.xml b/system/doc/installation_guide/part.xml index 0aacd0f49b..7e51e6ae84 100644 --- a/system/doc/installation_guide/part.xml +++ b/system/doc/installation_guide/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>2000</year><year>2014</year> + <year>2000</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/system/doc/installation_guide/xmlfiles.mk b/system/doc/installation_guide/xmlfiles.mk index 05effe1534..3f720e1ee5 100644 --- a/system/doc/installation_guide/xmlfiles.mk +++ b/system/doc/installation_guide/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009-2014. 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/system/doc/oam/Makefile b/system/doc/oam/Makefile index 32453428ef..42b979be85 100644 --- a/system/doc/oam/Makefile +++ b/system/doc/oam/Makefile @@ -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/system/doc/oam/book.xml b/system/doc/oam/book.xml index 93f5fe344a..05aa2334a5 100644 --- a/system/doc/oam/book.xml +++ b/system/doc/oam/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/system/doc/oam/oam_intro.xml b/system/doc/oam/oam_intro.xml index 22a2080fd9..8b8d69e638 100644 --- a/system/doc/oam/oam_intro.xml +++ b/system/doc/oam/oam_intro.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -178,7 +178,7 @@ <section> <title>MIB Structure</title> <p>The top-level OTP MIB is called <c>OTP-REG</c> and it is - included in the <c>sasl</c> application. All other OTP MIBs + included in the SASL application. All other OTP MIBs import some objects from this MIB.</p> <p>Each MIB is contained in one application. The MIB text @@ -188,7 +188,7 @@ <c><![CDATA[include/<MIB>.hrl]]></c>, and the compiled MIBs are stored under <c><![CDATA[priv/mibs/<MIB>.bin]]></c>. For example, the <c>OTP-MIB</c> is included in the - <c>sasl</c> application:</p> + SASL application:</p> <code type="none"> sasl-1.3/mibs/OTP-MIB.mib @@ -211,11 +211,11 @@ snmp:c("MY-MIB", [{il, ["sasl/priv/mibs"]}]).</code> <p>The following MIBs are defined in the OTP system:</p> <list type="bulleted"> - <item><p><c>OTP-REG)</c> (in <c>sasl</c>) contains the top-level + <item><p><c>OTP-REG)</c> (in SASL) contains the top-level OTP registration objects, used by all other MIBs.</p></item> - <item><p><c>OTP-TC</c> (in <c>sasl</c>) contains the general + <item><p><c>OTP-TC</c> (in SASL) contains the general Textual Conventions, which can be used by any other MIB.</p></item> - <item><p><c>OTP-MIB</c> (in <c>sasl</c>) contains objects for + <item><p><c>OTP-MIB</c> (in SASL) contains objects for instrumentation of the Erlang nodes, the Erlang machines, and the applications in the system.</p></item> <item><p><c>OTP-OS-MON-MIB</c> (in <c>oc_mon</c>) contains diff --git a/system/doc/oam/part.xml b/system/doc/oam/part.xml index efbaa05b94..817b70751c 100644 --- a/system/doc/oam/part.xml +++ b/system/doc/oam/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <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/system/doc/oam/xmlfiles.mk b/system/doc/oam/xmlfiles.mk index 5876243466..b2351c661c 100644 --- a/system/doc/oam/xmlfiles.mk +++ b/system/doc/oam/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009. 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/system/doc/programming_examples/Makefile b/system/doc/programming_examples/Makefile index fe59dce7e4..4d4aebcbc1 100644 --- a/system/doc/programming_examples/Makefile +++ b/system/doc/programming_examples/Makefile @@ -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/system/doc/programming_examples/book.xml b/system/doc/programming_examples/book.xml index c6eb4fec97..0f0fca5874 100644 --- a/system/doc/programming_examples/book.xml +++ b/system/doc/programming_examples/book.xml @@ -4,7 +4,7 @@ <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <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/system/doc/programming_examples/funs.xmlsrc b/system/doc/programming_examples/funs.xmlsrc index 8469f0871c..bb519be612 100644 --- a/system/doc/programming_examples/funs.xmlsrc +++ b/system/doc/programming_examples/funs.xmlsrc @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2013</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -212,7 +212,7 @@ f(...) -> ... end, ...) ...</code> - <p>instead of writng the following code:</p> + <p>instead of writing the following code:</p> <code type="none"> f(...) -> Y = ... diff --git a/system/doc/programming_examples/list_comprehensions.xml b/system/doc/programming_examples/list_comprehensions.xml index 5667571ec5..706cb337ad 100644 --- a/system/doc/programming_examples/list_comprehensions.xml +++ b/system/doc/programming_examples/list_comprehensions.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/programming_examples/part.xml b/system/doc/programming_examples/part.xml index e1f8cc5d57..930646ff4b 100644 --- a/system/doc/programming_examples/part.xml +++ b/system/doc/programming_examples/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <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/system/doc/programming_examples/records.xml b/system/doc/programming_examples/records.xml index 6bda6dc0fd..074aa636b4 100644 --- a/system/doc/programming_examples/records.xml +++ b/system/doc/programming_examples/records.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2013</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -93,7 +93,7 @@ person</pre> at compile time, not at runtime. For details on records in the shell, see the <seealso marker="stdlib:shell">shell(3)</seealso> - manual page in <c>stdlib</c>.</p> + manual page in STDLIB.</p> </section> <section> diff --git a/system/doc/programming_examples/xmlfiles.mk b/system/doc/programming_examples/xmlfiles.mk index cc77f48253..5129e488f4 100644 --- a/system/doc/programming_examples/xmlfiles.mk +++ b/system/doc/programming_examples/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009. 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/system/doc/reference_manual/Makefile b/system/doc/reference_manual/Makefile index bf0567932c..b09bf5496c 100644 --- a/system/doc/reference_manual/Makefile +++ b/system/doc/reference_manual/Makefile @@ -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/system/doc/reference_manual/book.xml b/system/doc/reference_manual/book.xml index 6b7306fb77..590d3580a4 100644 --- a/system/doc/reference_manual/book.xml +++ b/system/doc/reference_manual/book.xml @@ -4,7 +4,7 @@ <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <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/system/doc/reference_manual/code_loading.xml b/system/doc/reference_manual/code_loading.xml index e9da40e02f..f5e5e74841 100644 --- a/system/doc/reference_manual/code_loading.xml +++ b/system/doc/reference_manual/code_loading.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2015</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -130,26 +130,6 @@ loop() -> <marker id="on_load"></marker> <title>Running a Function When a Module is Loaded</title> - <warning> - <p>The <c>on_load</c> feature is to be considered experimental - as there are a number of known weak points in current semantics, - which therefore might change in future Erlang/OTP releases:</p> - <list> - <item><p>Doing external call in <c>on_load</c> to the module itself - leads to deadlock.</p></item> - <item><p>At module upgrade, other processes calling the module - get suspended waiting for <c>on_load</c> to finish. This can be very bad - for applications with demands on realtime characteristics.</p></item> - <item><p>At module upgrade, no rollback is done if the - <c>on_load</c> function fails. - The system is left in a bad limbo state without any working - and reachable instance of the module.</p></item> - </list> - <p>The problems with module upgrade described above can be fixed in future - Erlang/OTP releases by changing the behaviour to not make the module reachable until - after the <c>on_load</c> function has successfully returned.</p> - </warning> - <p>The <c>-on_load()</c> directive names a function that is to be run automatically when a module is loaded.</p> <p>Its syntax is as follows:</p> @@ -159,20 +139,35 @@ loop() -> <p>It is not necessary to export the function. It is called in a freshly spawned process (which terminates as soon as the function - returns). The function must return <c>ok</c> if the module is to - remain loaded and become callable, or any other value if the module - is to be unloaded. Generating an exception also causes the - module to be unloaded. If the return value is not an atom, - a warning error report is sent to the error logger.</p> - - <p>A process that calls any function in a module whose <c>on_load</c> - function has not yet returned, is suspended until the <c>on_load</c> - function has returned.</p> + returns).</p> + + <p>The function must return <c>ok</c> if the module is to + become the new current code for the module and become + callable.</p> + + <p>Returning any other value or generating an exception + causes the new code to be unloaded. If the return value is not an + atom, a warning error report is sent to the error logger.</p> + + <p>If there already is current code for the module, that code will + remain current and can be called until the <c>on_load</c> function + has returned. If the <c>on_load</c> function fails, the current + code (if any) will remain current. If there is no current code for + a module, any process that makes an external call to the module + before the <c>on_load</c> function has finished will be suspended + until the <c>on_load</c> function have finished.</p> + + <note> + <p>Before OTP 19, if the <c>on_load</c> function failed, any + previously current code would become old, essentially leaving + the system without any working and reachable instance of the + module. That problem has been eliminated in OTP 19.</p> + </note> <p>In embedded mode, first all modules are loaded. Then all <c>on_load</c> functions are called. The system is terminated unless all of the <c>on_load</c> functions return - <c>ok</c></p>. + <c>ok</c>.</p> <p><em>Example:</em></p> diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml index 893398b71b..1a3d19aed1 100644 --- a/system/doc/reference_manual/expressions.xml +++ b/system/doc/reference_manual/expressions.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2015</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -245,13 +245,13 @@ lists:keysearch(Name, 1, List)</code> handle(Msg, State) spawn(m, init, [])</code> <p><em>Examples</em> where <c>ExprF</c> is a fun:</p> - <code type="none"> -Fun1 = fun(X) -> X+1 end -Fun1(3) -=> 4 - -fun lists:append/2([1,2], [3,4]) -=> [1,2,3,4]</code> + <pre> +1> <input>Fun1 = fun(X) -> X+1 end,</input> +<input>Fun1(3).</input> +4 +2> <input>fun lists:append/2([1,2], [3,4]).</input> +[1,2,3,4] +3> </pre> <p>Notice that when calling a local function, there is a difference between using the implicitly or fully qualified function name. @@ -1004,7 +1004,7 @@ M4 = M3#{a := 2, b := 3}. % 'a' and 'b' was added in `M1` and `M2`.</code> </p> <list> <item><p>A <c>badmatch</c> exception.</p> - <p>This is if it is used in the context of the matching operator + <p>This is if it is used in the context of the match operator as in the example.</p> </item> <item><p>Or resulting in the next clause being tested in function heads and @@ -1085,7 +1085,7 @@ Ei = Value | <p>Used in a bit string construction, <c>Value</c> is an expression that is to evaluate to an integer, float, or bit string. If the expression is not a single literal or variable, it - is to be enclosed in parenthesis.</p> + is to be enclosed in parentheses.</p> <p>Used in a bit string matching, <c>Value</c> must be a variable, or an integer, float, or string.</p> @@ -1319,7 +1319,7 @@ catch Expr</code> {'EXIT',{badarith,[...]}}</pre> <p>Notice that <c>catch</c> has low precedence and catch subexpressions often needs to be enclosed in a block - expression or in parenthesis:</p> + expression or in parentheses:</p> <pre> 3> <input>A = catch 1+2.</input> ** 1: syntax error before: 'catch' ** @@ -1541,7 +1541,16 @@ end</pre> <pre> 1> <input>[X*2 || X <- [1,2,3]].</input> [2,4,6]</pre> - <p>More examples are provoded in + <p>When there are no generators or bit string generators, a list comprehension + returns either a list with one element (the result of evaluating <c>Expr</c>) + if all filters are true or an empty list otherwise.</p> + <p><em>Example:</em></p> + <pre> +1> <input>[2 || is_integer(2)].</input> +[2] +2> <input>[x || is_integer(x)].</input> +[]</pre> + <p>More examples are provided in <seealso marker="doc/programming_examples:list_comprehensions"> Programming Examples.</seealso></p> @@ -1556,9 +1565,11 @@ end</pre> <p>Bit string comprehensions are written with the following syntax:</p> <pre> -<< BitString || Qualifier1,...,QualifierN >></pre> - <p>Here, <c>BitString</c> is a bit string expression and each - <c>Qualifier</c> is either a generator, a bit string generator or a filter.</p> +<< BitStringExpr || Qualifier1,...,QualifierN >></pre> + <p><c>BitStringExpr</c> is an expression that evalutes to a bit + string. If <c>BitStringExpr</c> is a function call, it must be + enclosed in parentheses. Each <c>Qualifier</c> is either a + generator, a bit string generator or a filter.</p> <list type="bulleted"> <item>A <em>generator</em> is written as: <br></br> <c><![CDATA[Pattern <- ListExpr]]></c>. <br></br> diff --git a/system/doc/reference_manual/macros.xml b/system/doc/reference_manual/macros.xml index 3b1f72e5d6..5f24473557 100644 --- a/system/doc/reference_manual/macros.xml +++ b/system/doc/reference_manual/macros.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2015</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -146,6 +146,10 @@ bar(X) -> <item>The current line number.</item> <tag><c>?MACHINE</c>.</tag> <item>The machine name, <c>'BEAM'</c>.</item> + <tag><c>?FUNCTION_NAME</c></tag> + <item>The name of the current function.</item> + <tag><c>?FUNCTION_ARITY</c></tag> + <item>The arity (number of arguments) for the current function.</item> </taglist> </section> @@ -230,6 +234,53 @@ or </section> <section> + <title>-error() and -warning() directives</title> + + <p>The directive <c>-error(Term)</c> causes a compilation error.</p> + + <p><em>Example:</em></p> + <code type="none"> +-module(t). +-export([version/0]). + +-ifdef(VERSION). +version() -> ?VERSION. +-else. +-error("Macro VERSION must be defined."). +version() -> "". +-endif.</code> + + <p>The error message will look like this:</p> + + <pre> +% <input>erlc t.erl</input> +t.erl:7: -error("Macro VERSION must be defined.").</pre> + + <p>The directive <c>-warning(Term)</c> causes a compilation warning.</p> + + <p><em>Example:</em></p> + <code type="none"> +-module(t). +-export([version/0]). + +-ifndef(VERSION). +-warning("Macro VERSION not defined -- using default version."). +-define(VERSION, "0"). +-endif. +version() -> ?VERSION.</code> + + <p>The warning message will look like this:</p> + + <pre> +% <input>erlc t.erl</input> +t.erl:5: Warning: -warning("Macro VERSION not defined -- using default version.").</pre> + + <p>The <c>-error()</c> and <c>-warning()</c> directives were added + in OTP 19.</p> + + </section> + + <section> <title>Stringifying Macro Arguments</title> <p>The construction <c>??Arg</c>, where <c>Arg</c> is a macro argument, is expanded to a string containing the tokens of @@ -249,5 +300,6 @@ io:format("Call ~s: ~w~n",["you : function ( 2 , 1 )",you:function(2,1)]).</code <p>That is, a trace output, with both the function called and the resulting value.</p> </section> + </chapter> diff --git a/system/doc/reference_manual/modules.xml b/system/doc/reference_manual/modules.xml index 5f2ac2a67d..96968b547e 100644 --- a/system/doc/reference_manual/modules.xml +++ b/system/doc/reference_manual/modules.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2015</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -144,6 +144,7 @@ fact(0) -> % | <list type="bulleted"> <item><c>gen_server</c></item> <item><c>gen_fsm</c></item> + <item><c>gen_statem</c></item> <item><c>gen_event</c></item> <item><c>supervisor</c></item> </list> diff --git a/system/doc/reference_manual/part.xml b/system/doc/reference_manual/part.xml index 58483b099a..3d31157973 100644 --- a/system/doc/reference_manual/part.xml +++ b/system/doc/reference_manual/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>2003</year><year>2014</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/system/doc/reference_manual/patterns.xml b/system/doc/reference_manual/patterns.xml index 043d282de7..57b84b4dfc 100644 --- a/system/doc/reference_manual/patterns.xml +++ b/system/doc/reference_manual/patterns.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml index 22627058c1..a0ea41cb3b 100644 --- a/system/doc/reference_manual/typespec.xml +++ b/system/doc/reference_manual/typespec.xml @@ -4,14 +4,14 @@ <chapter> <header> <copyright> - <year>2003</year><year>2015</year> + <year>2003</year><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 @@ -47,7 +47,7 @@ <list type="bulleted"> <item>To document function interfaces</item> <item>To provide more information for bug detection tools, - such as <c>Dialyzer</c></item> + such as Dialyzer</item> <item>To be exploited by documentation tools, such as EDoc, for generating program documentation of various forms</item> </list> @@ -63,13 +63,13 @@ Types consist of, and are built from, a set of predefined types, for example, <c>integer()</c>, <c>atom()</c>, and <c>pid()</c>. Predefined types represent a typically infinite set of Erlang terms that - belong to this type. For example, the type <c>atom()</c> stands for the + belong to this type. For example, the type <c>atom()</c> denotes the set of all Erlang atoms. </p> <p> For integers and atoms, it is allowed for singleton types; for example, the integers - <c>-1</c> and <c>42</c>, or the atoms <c>'foo'</c> and <c>'bar'</c>). + <c>-1</c> and <c>42</c>, or the atoms <c>'foo'</c> and <c>'bar'</c>. All other types are built using unions of either predefined types or singleton types. In a type union between a type and one @@ -131,16 +131,19 @@ | nonempty_improper_list(Type1, Type2) %% Type1 and Type2 as above | nonempty_list(Type) %% Proper non-empty list - Map :: map() %% stands for a map of any size - | #{} %% stands for a map of any size + Map :: map() %% denotes a map of any size + | #{} %% denotes the empty map | #{PairList} - Tuple :: tuple() %% stands for a tuple of any size + Tuple :: tuple() %% denotes a tuple of any size | {} | {TList} - PairList :: Type => Type - | Type => Type, PairList + PairList :: Pair + | Pair, PairList + + Pair :: Type := Type %% denotes a mandatory pair + | Type => Type %% denotes an optional pair TList :: Type | Type, TList @@ -148,9 +151,9 @@ Union :: Type1 | Type2 ]]></pre> <p> - The general form of bitstrings is <c><<_:M, _:_*N>></c>, + The general form of bit strings is <c><<_:M, _:_*N>></c>, where <c>M</c> and <c>N</c> are positive integers. It denotes a - bitstring that is <c>M + (k*N)</c> bits long (that is, a bitstring that + bit string that is <c>M + (k*N)</c> bits long (that is, a bit string that starts with <c>M</c> bits and continues with <c>k</c> segments of <c>N</c> bits each, where <c>k</c> is also a positive integer). The notations <c><<_:_*N>></c>, <c><<_:M>></c>, @@ -158,7 +161,7 @@ that <c>M</c> or <c>N</c>, or both, are zero. </p> <p> - Because lists are commonly used, they have shorthand type notations. + Because lists are commonly used, they have shorthand type notations. The types <c>list(T)</c> and <c>nonempty_list(T)</c> have the shorthands <c>[T]</c> and <c>[T,...]</c>, respectively. The only difference between the two shorthands is that <c>[T]</c> can be an @@ -166,12 +169,27 @@ </p> <p> Notice that the shorthand for <c>list()</c>, that is, the list of - elements of unknown type, is <c>[_]</c> (or <c>[any()]</c>), not <c>[]</c>. + elements of unknown type, is <c>[_]</c> (or <c>[any()]</c>), not <c>[]</c>. The notation <c>[]</c> specifies the singleton type for the empty list. </p> <p> - For convenience, the following types are also built-in. - They can be thought as predefined aliases for the type unions also shown in + The general form of maps is <c>#{PairList}</c>. The key types in + <c>PairList</c> are allowed to overlap, and if they do, the + leftmost pair takes precedence. A map pair has a key in + <c>PairList</c> if it belongs to this type. A <c>PairList</c> may contain + both 'mandatory' and 'optional' pairs where 'mandatory' denotes that + a key type, and its associated value type, must be present. + In the case of an 'optional' pair it is not required for the key type to + be present. + </p> + <p> + Notice that the syntactic representation of <c>map()</c> is + <c>#{any() => any()}</c> (or <c>#{_ => _}</c>), not <c>#{}</c>. + The notation <c>#{}</c> specifies the singleton type for the empty map. + </p> + <p> + For convenience, the following types are also built-in. + They can be thought as predefined aliases for the type unions also shown in the table. </p> <table> @@ -187,37 +205,37 @@ <row> <cell><c>bitstring()</c></cell><cell><c><<_:_*1>></c></cell> </row> - <row> + <row> <cell><c>boolean()</c></cell><cell><c>'false' | 'true'</c></cell> </row> - <row> + <row> <cell><c>byte()</c></cell><cell><c>0..255</c></cell> </row> <row> <cell><c>char()</c></cell><cell><c>0..16#10ffff</c></cell> </row> - <row> + <row> <cell><c>nil()</c></cell><cell><c>[]</c></cell> </row> <row> <cell><c>number()</c></cell><cell><c>integer() | float()</c></cell> </row> - <row> + <row> <cell><c>list()</c></cell><cell><c>[any()]</c></cell> </row> - <row> + <row> <cell><c>maybe_improper_list()</c></cell><cell><c>maybe_improper_list(any(), any())</c></cell> </row> - <row> + <row> <cell><c>nonempty_list()</c></cell><cell><c>nonempty_list(any())</c></cell> </row> <row> <cell><c>string()</c></cell><cell><c>[char()]</c></cell> </row> - <row> + <row> <cell><c>nonempty_string()</c></cell><cell><c>[char(),...]</c></cell> </row> - <row> + <row> <cell><c>iodata()</c></cell><cell><c>iolist() | binary()</c></cell> </row> <row> @@ -229,7 +247,7 @@ <row> <cell><c>module()</c></cell><cell><c>atom()</c></cell> </row> - <row> + <row> <cell><c>mfa()</c></cell><cell><c>{module(),atom(),arity()}</c></cell> </row> <row> @@ -245,7 +263,7 @@ <cell><c>timeout()</c></cell><cell><c>'infinity' | non_neg_integer()</c></cell> </row> <row> - <cell><c>no_return()</c></cell><cell><c>none()</c></cell> + <cell><c>no_return()</c></cell><cell><c>none()</c></cell> </row> <tcaption>Built-in types, predefined aliases</tcaption> </table> @@ -270,11 +288,11 @@ </row> <tcaption>Additional built-in types</tcaption> </table> - + <p> Users are not allowed to define types with the same names as the predefined or built-in ones. This is checked by the compiler and - its violation results in a compilation error. + its violation results in a compilation error. </p> <note> <p> @@ -302,12 +320,6 @@ This is described in <seealso marker="#typeinrecords"> Type Information in Record Declarations</seealso>. </p> - <note> - <p>Map types, both <c>map()</c> and <c>#{...}</c>, - are considered experimental during OTP 17.</p> - <p>No type information of maps pairs, only the containing map types, - are used by Dialyzer in OTP 17.</p> - </note> </section> <section> @@ -386,13 +398,13 @@ <pre> -record(rec, {field1 :: Type1, field2, field3 :: Type3}).</pre> <p> - For fields without type annotations, their type defaults to any(). + For fields without type annotations, their type defaults to any(). That is, the previous example is a shorthand for the following: </p> <pre> -record(rec, {field1 :: Type1, field2 :: any(), field3 :: Type3}).</pre> <p> - In the presence of initial values for fields, + In the presence of initial values for fields, the type must be declared after the initialization, as follows: </p> <pre> @@ -401,11 +413,13 @@ The initial values for fields are to be compatible with (that is, a member of) the corresponding types. This is checked by the compiler and results in a compilation error - if a violation is detected. For fields without initial values, - the singleton type <c>'undefined'</c> is added to all declared types. - In other words, the following two record declarations have identical - effects: + if a violation is detected. </p> + <note> + <p>Before Erlang/OTP 19, for fields without initial values, + the singleton type <c>'undefined'</c> was added to all declared types. + In other words, the following two record declarations had identical + effects:</p> <pre> -record(rec, {f1 = 42 :: integer(), f2 :: float(), @@ -415,26 +429,27 @@ f2 :: 'undefined' | float(), f3 :: 'undefined' | 'a' | 'b'}).</pre> <p> - For this reason, it is recommended that records contain initializers, - whenever possible. + This is no longer the case. If you require <c>'undefined'</c> in your record field + type, you must explicitly add it to the typespec, as in the 2nd example. </p> + </note> <p> - Any record, containing type information or not, once defined, + Any record, containing type information or not, once defined, can be used as a type using the following syntax: </p> <pre> #rec{}</pre> <p> - In addition, the record fields can be further specified when using + In addition, the record fields can be further specified when using a record type by adding type information about the field as follows: </p> <pre> #rec{some_field :: Type}</pre> <p> - Any unspecified fields are assumed to have the type in the original + Any unspecified fields are assumed to have the type in the original record declaration. </p> </section> - + <section> <title>Specifications for Functions</title> <p> @@ -448,9 +463,9 @@ else a compilation error occurs. </p> <p> - This form can also be used in header files (.hrl) to declare type - information for exported functions. - Then these header files can be included in files that (implicitly or + This form can also be used in header files (.hrl) to declare type + information for exported functions. + Then these header files can be included in files that (implicitly or explicitly) import these functions. </p> <p> @@ -464,14 +479,14 @@ <pre> -spec Function(ArgName1 :: Type1, ..., ArgNameN :: TypeN) -> RT.</pre> <p> - A function specification can be overloaded. + A function specification can be overloaded. That is, it can have several types, separated by a semicolon (<c>;</c>): </p> <pre> -spec foo(T1, T2) -> T3 ; (T4, T5) -> T6.</pre> <p> - A current restriction, which currently results in a warning + A current restriction, which currently results in a warning (not an error) by the compiler, is that the domains of the argument types cannot overlap. For example, the following specification results in a warning: @@ -480,9 +495,9 @@ -spec foo(pos_integer()) -> pos_integer() ; (integer()) -> integer().</pre> <p> - Type variables can be used in specifications to specify relations for - the input and output arguments of a function. - For example, the following specification defines the type of a + Type variables can be used in specifications to specify relations for + the input and output arguments of a function. + For example, the following specification defines the type of a polymorphic identity function: </p> <pre> @@ -495,7 +510,8 @@ </p> <pre> -spec id(X) -> X when X :: tuple().</pre> <p> - Currently, the <c>::</c> constraint (read as <c>is_subtype</c>) is + Currently, the <c>::</c> constraint + (read as «is a subtype of») is the only guard constraint that can be used in the <c>'when'</c> part of a <c>'-spec'</c> attribute. </p> @@ -513,7 +529,7 @@ <em>the same</em> tuple. </p> <p> - However, it is up to the tools that process the specificationss + However, it is up to the tools that process the specifications to choose whether to take this extra information into account or not. </p> @@ -529,19 +545,9 @@ <pre> -spec foo({X, integer()}) -> X when X :: atom() ; ([Y]) -> Y when Y :: number().</pre> - <note> - <p> - For backwards compatibility the following form is also allowed: - </p> - <pre> -spec id(X) -> X when is_subtype(X, tuple()).</pre> - <p> - but its use is discouraged. It will be removed in a future - Erlang/OTP release. - </p> - </note> <p> - Some functions in Erlang are not meant to return; - either because they define servers or because they are used to + Some functions in Erlang are not meant to return; + either because they define servers or because they are used to throw exceptions, as in the following function: </p> <pre> my_error(Err) -> erlang:throw({error, Err}).</pre> @@ -553,4 +559,3 @@ <pre> -spec my_error(term()) -> no_return().</pre> </section> </chapter> - diff --git a/system/doc/reference_manual/xmlfiles.mk b/system/doc/reference_manual/xmlfiles.mk index 323b94c0de..61637ae701 100644 --- a/system/doc/reference_manual/xmlfiles.mk +++ b/system/doc/reference_manual/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009. 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/system/doc/system_architecture_intro/Makefile b/system/doc/system_architecture_intro/Makefile index 5e41ab7b85..5000df6038 100644 --- a/system/doc/system_architecture_intro/Makefile +++ b/system/doc/system_architecture_intro/Makefile @@ -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/system/doc/system_architecture_intro/book.xml b/system/doc/system_architecture_intro/book.xml index 318f940a18..4b9f03c7f9 100644 --- a/system/doc/system_architecture_intro/book.xml +++ b/system/doc/system_architecture_intro/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/system/doc/system_architecture_intro/part.xml b/system/doc/system_architecture_intro/part.xml index eb0f9e0ba6..c000892449 100644 --- a/system/doc/system_architecture_intro/part.xml +++ b/system/doc/system_architecture_intro/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <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/system/doc/system_architecture_intro/sys_arch_intro.xml b/system/doc/system_architecture_intro/sys_arch_intro.xml index b9535f66f8..cf75e1f100 100644 --- a/system/doc/system_architecture_intro/sys_arch_intro.xml +++ b/system/doc/system_architecture_intro/sys_arch_intro.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/system_architecture_intro/xmlfiles.mk b/system/doc/system_architecture_intro/xmlfiles.mk index 6e7e712703..60c2047796 100644 --- a/system/doc/system_architecture_intro/xmlfiles.mk +++ b/system/doc/system_architecture_intro/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009. 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/system/doc/system_principles/Makefile b/system/doc/system_principles/Makefile index 93f0147aa4..657e02024f 100644 --- a/system/doc/system_principles/Makefile +++ b/system/doc/system_principles/Makefile @@ -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/system/doc/system_principles/book.xml b/system/doc/system_principles/book.xml index 11eacba578..cd84d4cf6b 100644 --- a/system/doc/system_principles/book.xml +++ b/system/doc/system_principles/book.xml @@ -4,7 +4,7 @@ <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <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/system/doc/system_principles/create_target.xmlsrc b/system/doc/system_principles/create_target.xmlsrc index ccc26081c3..f9b27ffc35 100644 --- a/system/doc/system_principles/create_target.xmlsrc +++ b/system/doc/system_principles/create_target.xmlsrc @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2002</year><year>2014</year> + <year>2002</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -374,10 +374,10 @@ os> <input>/usr/local/erl-target/bin/to_erl /tmp/erlang.pipe.1</input></pre> </p> <pre> 2> <input>release_handler:install_release(Vsn).</input> -<output>{continue_after_restart,"FIRST",[]} +{continue_after_restart,"FIRST",[]} heart: Tue Apr 1 12:15:10 2014: Erlang has closed. heart: Tue Apr 1 12:15:11 2014: Executed "/usr/local/erl-target/bin/start /usr/local/erl-target/releases/new_start_erl.data" -> 0. Terminating. -[End]</output></pre> +[End]</pre> <p> The above return value and output after the call to <c>release_handler:install_release/1</c> means that the @@ -398,12 +398,12 @@ os> <input>/usr/local/erl-target/bin/to_erl /tmp/erlang.pipe.2</input></pre> </p> <pre> 1> <input>release_handler:which_releases().</input> -<output>[{"MYSYSTEM","SECOND", +[{"MYSYSTEM","SECOND", ["kernel-3.0","stdlib-2.0","sasl-2.4","pea-2.0"], current}, {"MYSYSTEM","FIRST", ["kernel-2.16.4","stdlib-1.19.4","sasl-2.3.4","pea-1.0"], - permanent}]</output></pre> + permanent}]</pre> <p> Our new release, "SECOND", is now the current release, but we can also see that our "FIRST" release is still permanent. This @@ -420,12 +420,12 @@ os> <input>/usr/local/erl-target/bin/to_erl /tmp/erlang.pipe.2</input></pre> </p> <pre> 3> <input>release_handler:which_releases().</input> -<output>[{"MYSYSTEM","SECOND", +[{"MYSYSTEM","SECOND", ["kernel-3.0","stdlib-2.0","sasl-2.4","pea-2.0"], permanent}, {"MYSYSTEM","FIRST", ["kernel-2.16.4","stdlib-1.19.4","sasl-2.3.4","pea-1.0"], - old}]</output></pre> + old}]</pre> <p> We see that the new release version is <c>permanent</c>, so it would be safe to restart the node.</p> diff --git a/system/doc/system_principles/error_logging.xml b/system/doc/system_principles/error_logging.xml index 024137a430..c99d59ddb7 100644 --- a/system/doc/system_principles/error_logging.xml +++ b/system/doc/system_principles/error_logging.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/system_principles/part.xml b/system/doc/system_principles/part.xml index 1557b5ff62..1b87ecd350 100644 --- a/system/doc/system_principles/part.xml +++ b/system/doc/system_principles/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1997</year><year>2014</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/system/doc/system_principles/upgrade.xml b/system/doc/system_principles/upgrade.xml index 173e46185c..c491bd855e 100644 --- a/system/doc/system_principles/upgrade.xml +++ b/system/doc/system_principles/upgrade.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2014</year> + <year>2014</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/system/doc/system_principles/versions.xml b/system/doc/system_principles/versions.xml index ee104a8302..b9f7fa4bf6 100644 --- a/system/doc/system_principles/versions.xml +++ b/system/doc/system_principles/versions.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2014</year> + <year>2014</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -57,11 +57,11 @@ <p>In an OTP source code tree, the OTP version can be read from the text file <c><OTP source root>/OTP_VERSION</c>. The absolute path to the file can be constructed by calling - <c>filename:join([<seealso marker="kernel:code#root_dir/0">code:root_dir()</seealso>, "OTP_VERSION"])</c>.</p> + <c>filename:join([</c><seealso marker="kernel:code#root_dir/0"><c>code:root_dir()</c></seealso><c>, "OTP_VERSION"])</c>.</p> <p>In an installed OTP development system, the OTP version can be read from the text file <c><OTP installation root>/releases/<OTP release number>/OTP_VERSION</c>. The absolute path to the file can by constructed by calling - <c>filename:join([<seealso marker="kernel:code#root_dir/0">code:root_dir()</seealso>, "releases", <seealso marker="erts:erlang#system_info_otp_release"> erlang:system_info(otp_release)</seealso>, "OTP_VERSION"]).</c></p> + <c>filename:join([</c><seealso marker="kernel:code#root_dir/0"><c>code:root_dir()</c></seealso><c>, "releases", </c><seealso marker="erts:erlang#system_info_otp_release"><c>erlang:system_info(otp_release)</c></seealso><c>, "OTP_VERSION"]).</c></p> <p>If the version read from the <c>OTP_VERSION</c> file in a development system has a <c>**</c> suffix, the system has been patched using the diff --git a/system/doc/system_principles/xmlfiles.mk b/system/doc/system_principles/xmlfiles.mk index fcc1fc886f..c3c3bb4731 100644 --- a/system/doc/system_principles/xmlfiles.mk +++ b/system/doc/system_principles/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009-2014. 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/system/doc/top/Makefile b/system/doc/top/Makefile index 9be91d6ac0..aa951b0db8 100644 --- a/system/doc/top/Makefile +++ b/system/doc/top/Makefile @@ -1,7 +1,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. @@ -35,7 +35,7 @@ RELSYSDIR = "$(RELEASE_PATH)/doc" GIF_FILES = -INFO_FILES = ../../README ../../COPYRIGHT PR.template +INFO_FILES = ../../../README.md ../../COPYRIGHT PR.template TOPDOCDIR=. @@ -74,6 +74,7 @@ XML_FILES = \ BOOK_FILES = book.xml +XMLLINT_SRCDIRS= ../installation_guide:../system_principles:../embedded:../getting_started:../reference_manual:../programming_examples:../efficiency_guide:../tutorial:../design_principles:../oam HTMLDIR= ../html PDFREFDIR= pdf diff --git a/system/doc/top/book.xml b/system/doc/top/book.xml index 7bbeb38472..c94b0f24d6 100644 --- a/system/doc/top/book.xml +++ b/system/doc/top/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/system/doc/top/src/erl_html_tools.erl b/system/doc/top/src/erl_html_tools.erl index dddf025020..d55c2e1164 100644 --- a/system/doc/top/src/erl_html_tools.erl +++ b/system/doc/top/src/erl_html_tools.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2011. 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. @@ -54,24 +54,24 @@ top_index() -> top_index(src, Value, filename:join(Value, "doc"), RelName) end. -top_index([src, RootDir, DestDir, OtpRel]) - when is_atom(RootDir), is_atom(DestDir), is_atom(OtpRel) -> - top_index(src, atom_to_list(RootDir), atom_to_list(DestDir), atom_to_list(OtpRel)); -top_index([rel, RootDir, DestDir, OtpRel]) - when is_atom(RootDir), is_atom(DestDir), is_atom(OtpRel) -> - top_index(rel, atom_to_list(RootDir), atom_to_list(DestDir), atom_to_list(OtpRel)); +top_index([src, RootDir, DestDir, OtpBaseVsn]) + when is_atom(RootDir), is_atom(DestDir), is_atom(OtpBaseVsn) -> + top_index(src, atom_to_list(RootDir), atom_to_list(DestDir), atom_to_list(OtpBaseVsn)); +top_index([rel, RootDir, DestDir, OtpBaseVsn]) + when is_atom(RootDir), is_atom(DestDir), is_atom(OtpBaseVsn) -> + top_index(rel, atom_to_list(RootDir), atom_to_list(DestDir), atom_to_list(OtpBaseVsn)); top_index(RootDir) when is_atom(RootDir) -> {_,RelName} = init:script_id(), top_index(rel, RootDir, filename:join(RootDir, "doc"), RelName). -top_index(Source, RootDir, DestDir, OtpRel) -> +top_index(Source, RootDir, DestDir, OtpBaseVsn) -> report("****\nRootDir: ~p", [RootDir]), report("****\nDestDir: ~p", [DestDir]), - report("****\nOtpRel: ~p", [OtpRel]), + report("****\nOtpBaseVsn: ~p", [OtpBaseVsn]), - put(otp_release, OtpRel), + put(otp_base_vsn, OtpBaseVsn), Templates = find_templates(["","templates",DestDir]), report("****\nTemplates: ~p", [Templates]), @@ -81,9 +81,9 @@ top_index(Source, RootDir, DestDir, OtpRel) -> report("****\nGroups: ~p", [Groups]), process_templates(Templates, DestDir, Groups). -top_index_silent(RootDir, DestDir, OtpRel) -> +top_index_silent(RootDir, DestDir, OtpBaseVsn) -> put(silent,true), - Result = top_index(rel, RootDir, DestDir, OtpRel), + Result = top_index(rel, RootDir, DestDir, OtpBaseVsn), erase(silent), Result. @@ -361,7 +361,7 @@ subst_template_1(Group, Stream, Info) -> case file:read(Stream, 100000) of {ok, Template} -> Fun = fun(Match, _) -> {subst(Match, Info, Group),Info} end, - gsub(Template, "#[A-Za-z0-9]+#", Fun, Info); + gsub(Template, "#[A-Za-z_0-9]+#", Fun, Info); {error, Reason} -> {error, Reason} end. @@ -379,8 +379,8 @@ get_version(Info) -> "" end. -subst("#release#", _Info, _Group) -> - get(otp_release); +subst("#otp_base_vsn#", _Info, _Group) -> + get(otp_base_vsn); subst("#version#", Info, _Group) -> get_version(Info); subst("#copyright#", _Info, _Group) -> diff --git a/system/doc/top/src/erlresolvelinks.erl b/system/doc/top/src/erlresolvelinks.erl index 82b79d9f9f..c1285fa1c3 100644 --- a/system/doc/top/src/erlresolvelinks.erl +++ b/system/doc/top/src/erlresolvelinks.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2010. 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/system/doc/top/src/otp_man_index.erl b/system/doc/top/src/otp_man_index.erl index 753e952ecb..12aaba1423 100644 --- a/system/doc/top/src/otp_man_index.erl +++ b/system/doc/top/src/otp_man_index.erl @@ -2,7 +2,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/system/doc/top/templates/applications.html.src b/system/doc/top/templates/applications.html.src index 4be969f9d1..1f73c44d69 100644 --- a/system/doc/top/templates/applications.html.src +++ b/system/doc/top/templates/applications.html.src @@ -2,7 +2,7 @@ <!-- %CopyrightBegin% -Copyright Ericsson AB 2009-2010. 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/system/doc/top/templates/index.html.src b/system/doc/top/templates/index.html.src index bdac3895b0..d2a6736d34 100644 --- a/system/doc/top/templates/index.html.src +++ b/system/doc/top/templates/index.html.src @@ -2,7 +2,7 @@ <!-- %CopyrightBegin% -Copyright Ericsson AB 2009-2014. 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. @@ -22,7 +22,7 @@ limitations under the License. <html> <head> <link rel="stylesheet" href="otp_doc.css" type="text/css"/> - <title>Erlang/OTP #release#</title> + <title>Erlang/OTP #otp_base_vsn#</title> <script id="js" type="text/javascript" language="JavaScript" src="js/flipmenu/flipmenu.js"> @@ -36,7 +36,7 @@ limitations under the License. <div id="leftnav"> <div class="innertube"> <img alt="Erlang logo" src="erlang-logo.png"/ > -<!-- small><a href="glossary.html">Glossary</a> |--> +<p/> <small><a href="applications.html">Applications</a><br> <a href="man_index.html">Modules</a></small> <p/> @@ -74,7 +74,7 @@ limitations under the License. <div id="content"> <div class="innertube"> <center> -<font size="+1"><b>Erlang/OTP #release#</b></font><br> +<font size="+1"><b>Erlang/OTP #otp_base_vsn#</b></font><br> </center> <center> <p> @@ -108,7 +108,7 @@ In addition to the documentation here Erlang is described in several recent book <a href="http://shop.oreilly.com/product/0636920025818.do">"Introducing Erlang"</a> from O'Reilly. </li> <li> -<a href="http://www.nostarch.com/erlang">"Learn You Some Erlang for Great Good!"</a> from nostarch. +<a href="http://www.nostarch.com/erlang">"Learn You Some Erlang for Great Good!"</a> from No Starch Press. </li> <li> <a href="http://oreilly.com/catalog/9780596518189">"Erlang Programming"</a> from O'Reilly. @@ -119,6 +119,9 @@ In addition to the documentation here Erlang is described in several recent book <li> <a href="http://www.manning.com/logan">"Erlang and OTP in Action"</a> from Manning. </li> +<li> +<a href="http://shop.oreilly.com/product/0636920024149.do">"Designing for Scalability with Erlang/OTP"</a> from O'Reilly. +</li> </ul> <p> These books are highly recommended as a start for learning Erlang. @@ -129,14 +132,15 @@ href="applications.html">applications</a>. An application normally contains Erlang <a href="man_index.html">modules</a>. Some OTP applications, such as the C interface <em>erl_interface</em>, are written in other languages and have no Erlang modules. +<p></p> +</li> -<p> <li>On a Unix system you can view the manual pages from the command line using <pre> % erl -man <module> </pre> -<p> +</li> <li> You can of course use any editor you like to write Erlang programs, but if you use Emacs there exists editing support such as @@ -145,10 +149,10 @@ verification, comment support including paragraph filling, skeletons, tags support and more. See the <a href="#tools#/index.html"> Tools</a> application for details. <p> -There is also an -<a href="http://erlide.org/index.html"> -Erlang plugin (ErlIDE) for Eclipse</a> if you prefer a more graphical -environment. ErlIDE is under active development with new features in almost every release. +There are also Erlang plugins for +<a href="http://erlide.org/index.html">Eclipse (ErlIDE)</a> and +<a href="http://ignatov.github.io/intellij-erlang/">IntelliJ IDEA</a> +if you prefer a more graphical environment, which are both under active development. <li>When developing with Erlang/OTP you usually test your programs from the interactive shell (see <a href="getting_started/users_guide.html"> Getting Started With Erlang</a>) where you can call individual @@ -161,23 +165,27 @@ module and function name completion (tab) if the module is loaded. <li>OpenSource users can ask questions and share experiences on the <a href="http://www.erlang.org/static/doc/mailinglist.html"> -Erlang questions mailing list</a>. <p> +Erlang questions mailing list</a>. +<p></p> +</li> <li>Before asking a question you can browse the <a href="http://www.erlang.org/pipermail/erlang-questions/"> mailing list archive</a> and read the <a href="http://www.erlang.org/faq/faq.html" >Frequently -Asked Questions</a>. <p> +Asked Questions</a>. +<p></p> +</li> <li>Additional information and links of interest for Erlang programmers can be found on the Erlang Open Source site <a href="http://www.erlang.org/">http://www.erlang.org</a>. -<p> +</li> </ul> <center> <small> -Copyright © 1999-2013 +Copyright © 1999-2016 <a href="http://www.ericsson.com">Ericsson AB</a> </small> </center> diff --git a/system/doc/tutorial/Makefile b/system/doc/tutorial/Makefile index 7393dc9e9d..2eeb096e23 100644 --- a/system/doc/tutorial/Makefile +++ b/system/doc/tutorial/Makefile @@ -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/system/doc/tutorial/appendix.xmlsrc b/system/doc/tutorial/appendix.xmlsrc index 52c24c1b67..4be6c91fe9 100644 --- a/system/doc/tutorial/appendix.xmlsrc +++ b/system/doc/tutorial/appendix.xmlsrc @@ -4,7 +4,7 @@ <chapter> <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/system/doc/tutorial/book.xml b/system/doc/tutorial/book.xml index 81530f25eb..1841a2df60 100644 --- a/system/doc/tutorial/book.xml +++ b/system/doc/tutorial/book.xml @@ -4,7 +4,7 @@ <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <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/system/doc/tutorial/c_port.xmlsrc b/system/doc/tutorial/c_port.xmlsrc index 695f16515d..ff0997fb54 100644 --- a/system/doc/tutorial/c_port.xmlsrc +++ b/system/doc/tutorial/c_port.xmlsrc @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2000</year><year>2015</year> + <year>2000</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -98,11 +98,11 @@ loop(Port) -> {call, Caller, Msg} -> Port ! {self(), {command, encode(Msg)}}, receive - {Port, {data, Data}} -> + {Port, {data, Data}} -> Caller ! {complex, decode(Data)} end, loop(Port) - end.</pre> + end.</pre> <p>Assuming that both the arguments and the results from the C functions are less than 256, a simple encoding/decoding scheme is employed. In this scheme, <c>foo</c> is represented by byte diff --git a/system/doc/tutorial/c_portdriver.xmlsrc b/system/doc/tutorial/c_portdriver.xmlsrc index 933e2395a3..c4cf6daa3b 100644 --- a/system/doc/tutorial/c_portdriver.xmlsrc +++ b/system/doc/tutorial/c_portdriver.xmlsrc @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2000</year><year>2015</year> + <year>2000</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -161,8 +161,8 @@ decode([Int]) -> Int.</pre> <title>Running the Example</title> <p><em>Step 1.</em> Compile the C code:</p> <pre> -unix> <input>gcc -o exampledrv -fpic -shared complex.c port_driver.c</input> -windows> <input>cl -LD -MD -Fe exampledrv.dll complex.c port_driver.c</input></pre> +unix> <input>gcc -o example_drv.so -fpic -shared complex.c port_driver.c</input> +windows> <input>cl -LD -MD -Fe example_drv.dll complex.c port_driver.c</input></pre> <p><em>Step 2.</em> Start Erlang and compile the Erlang code:</p> <pre> > <input>erl</input> diff --git a/system/doc/tutorial/distribution.xml b/system/doc/tutorial/distribution.xml index 40d60acb3a..b489410841 100644 --- a/system/doc/tutorial/distribution.xml +++ b/system/doc/tutorial/distribution.xml @@ -4,7 +4,7 @@ <chapter> <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/system/doc/tutorial/part.xml b/system/doc/tutorial/part.xml index 5216d1653d..4a66f0cb22 100644 --- a/system/doc/tutorial/part.xml +++ b/system/doc/tutorial/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <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/system/doc/tutorial/xmlfiles.mk b/system/doc/tutorial/xmlfiles.mk index 28b66f232d..f8ed7be064 100644 --- a/system/doc/tutorial/xmlfiles.mk +++ b/system/doc/tutorial/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009-2010. 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. |