Packages

Ceylan-WOOPER, a Wrapper for Object-Oriented Programming in Erlang, as an OTP active application here (see http://wooper.esperide.org)

Current section

10 Versions

Jump to

Compare versions

76 files changed
+8807 additions
-6917 deletions
  @@ -3,37 +3,53 @@
3 3 {<<"description">>,
4 4 <<"Ceylan-WOOPER, a Wrapper for Object-Oriented Programming in Erlang, as an OTP active application here (see http://wooper.esperide.org)">>}.
5 5 {<<"files">>,
6 - [<<"LICENSE">>,<<"README.md">>,<<"priv/hex-packaging/doc/GNUmakefile">>,
7 - <<"priv/hex-packaging/hex-compile-hook-script.sh">>,
8 - <<"priv/hex-packaging/root/GNUmakefile">>,
9 - <<"priv/hex-packaging/root/GNUmakerules-automatic.inc">>,
10 - <<"priv/hex-packaging/root/GNUmakerules-explicit.inc">>,
11 - <<"priv/hex-packaging/root/GNUmakesettings.inc">>,
12 - <<"priv/hex-packaging/root/GNUmakevars.inc">>,<<"rebar.config">>,
6 + [<<"LICENSE">>,<<"README.md">>,<<"include/wooper.hrl">>,
7 + <<"include/wooper_class_manager.hrl">>,
8 + <<"include/wooper_classes_functions.hrl">>,
9 + <<"include/wooper_creation_functions.hrl">>,<<"include/wooper_debug.hrl">>,
10 + <<"include/wooper_defines_exports.hrl">>,
11 + <<"include/wooper_destruction_exports.hrl">>,
12 + <<"include/wooper_destruction_functions.hrl">>,
13 + <<"include/wooper_execute_exports.hrl">>,
14 + <<"include/wooper_execute_functions.hrl">>,
15 + <<"include/wooper_execute_internal_exports.hrl">>,
16 + <<"include/wooper_execute_internal_functions.hrl">>,
17 + <<"include/wooper_for_classes.hrl">>,<<"include/wooper_info.hrl">>,
18 + <<"include/wooper_main_loop_exports.hrl">>,
19 + <<"include/wooper_main_loop_functions.hrl">>,
20 + <<"include/wooper_serialisation_exports.hrl">>,
21 + <<"include/wooper_serialisation_functions.hrl">>,
22 + <<"include/wooper_state_exports.hrl">>,
23 + <<"include/wooper_state_functions.hrl">>,
24 + <<"include/wooper_types_exports.hrl">>,<<"priv/GNUmakefile">>,
25 + <<"priv/examples/GNUmakefile">>,<<"priv/examples/class_Cat.erl">>,
26 + <<"priv/examples/class_Cat_test.erl">>,
27 + <<"priv/examples/class_Creature.erl">>,
28 + <<"priv/examples/class_Creature_test.erl">>,
29 + <<"priv/examples/class_Mammal.erl">>,
30 + <<"priv/examples/class_Mammal_test.erl">>,
31 + <<"priv/examples/class_OvoviviparousBeing.erl">>,
32 + <<"priv/examples/class_OvoviviparousBeing_test.erl">>,
33 + <<"priv/examples/class_Platypus.erl">>,
34 + <<"priv/examples/class_Platypus_test.erl">>,
35 + <<"priv/examples/class_Reptile.erl">>,
36 + <<"priv/examples/class_Reptile_test.erl">>,
37 + <<"priv/examples/class_ViviparousBeing.erl">>,
38 + <<"priv/examples/class_ViviparousBeing_test.erl">>,
39 + <<"priv/examples/class_WOOPERTemplate.erl.sample">>,
40 + <<"priv/examples/class_WOOPERTemplate_test.erl.sample">>,
41 + <<"priv/examples/ecosystem_types.hrl">>,
42 + <<"priv/examples/serialisation_test.erl">>,<<"rebar.config">>,
13 43 <<"rebar.lock">>,<<"src/GNUmakefile">>,<<"src/wooper.app.src">>,
14 - <<"src/wooper.erl">>,<<"src/wooper.hrl">>,<<"src/wooper_app.erl">>,
44 + <<"src/wooper.erl">>,<<"src/wooper_app.erl">>,
15 45 <<"src/wooper_class_management.erl">>,<<"src/wooper_class_manager.erl">>,
16 - <<"src/wooper_class_manager.hrl">>,<<"src/wooper_classes_functions.hrl">>,
17 - <<"src/wooper_creation_functions.hrl">>,<<"src/wooper_debug.hrl">>,
18 - <<"src/wooper_defines_exports.hrl">>,
19 - <<"src/wooper_destruction_exports.hrl">>,
20 - <<"src/wooper_destruction_functions.hrl">>,
21 - <<"src/wooper_execute_exports.hrl">>,<<"src/wooper_execute_functions.hrl">>,
22 - <<"src/wooper_execute_internal_exports.hrl">>,
23 - <<"src/wooper_execute_internal_functions.hrl">>,
24 - <<"src/wooper_for_classes.hrl">>,<<"src/wooper_info.erl">>,
25 - <<"src/wooper_info.hrl">>,<<"src/wooper_instance_construction.erl">>,
46 + <<"src/wooper_info.erl">>,<<"src/wooper_instance_construction.erl">>,
26 47 <<"src/wooper_instance_destruction.erl">>,
27 48 <<"src/wooper_instance_proxy.erl">>,<<"src/wooper_internals.erl">>,
28 - <<"src/wooper_introspection.erl">>,<<"src/wooper_main_loop_exports.hrl">>,
29 - <<"src/wooper_main_loop_functions.hrl">>,
30 - <<"src/wooper_method_management.erl">>,<<"src/wooper_parse_transform.erl">>,
31 - <<"src/wooper_parse_utils.erl">>,<<"src/wooper_serialisation.erl">>,
32 - <<"src/wooper_serialisation_exports.hrl">>,
33 - <<"src/wooper_serialisation_functions.hrl">>,
34 - <<"src/wooper_state_exports.hrl">>,<<"src/wooper_state_functions.hrl">>,
35 - <<"src/wooper_state_management.erl">>,<<"src/wooper_sup.erl">>,
36 - <<"src/wooper_types_exports.hrl">>,<<"src/wooper_utils.erl">>]}.
49 + <<"src/wooper_introspection.erl">>,<<"src/wooper_method_management.erl">>,
50 + <<"src/wooper_parse_transform.erl">>,<<"src/wooper_parse_utils.erl">>,
51 + <<"src/wooper_serialisation.erl">>,<<"src/wooper_state_management.erl">>,
52 + <<"src/wooper_sup.erl">>,<<"src/wooper_utils.erl">>]}.
37 53 {<<"licenses">>,
38 54 [<<"Ceylan-WOOPER is licensed by its author (Olivier Boudeville) under a disjunctive tri-license, giving you the choice of one of the three following sets of free software/open source licensing terms:\n\t- the Mozilla Public License (MPL), version 1.1 or later (very close to the former Erlang Public License, except aspects regarding Ericsson and/or the Swedish law)\n\t- the GNU General Public License (GPL), version 3.0 or later\n\t- the GNU Lesser General Public License (LGPL), version 3.0 or later">>]}.
39 55 {<<"links">>,
  @@ -44,5 +60,5 @@
44 60 [{<<"myriad">>,
45 61 [{<<"app">>,<<"myriad">>},
46 62 {<<"optional">>,false},
47 - {<<"requirement">>,<<"1.0.11">>}]}]}.
48 - {<<"version">>,<<"2.0.6">>}.
63 + {<<"requirement">>,<<"1.0.14">>}]}]}.
64 + {<<"version">>,<<"2.0.7">>}.
  @@ -0,0 +1,188 @@
1 + % Copyright (C) 2003-2019 Olivier Boudeville
2 + %
3 + % This file is part of the Ceylan-WOOPER library.
4 + %
5 + % This library is free software: you can redistribute it and/or modify
6 + % it under the terms of the GNU Lesser General Public License or
7 + % the GNU General Public License, as they are published by the Free Software
8 + % Foundation, either version 3 of these Licenses, or (at your option)
9 + % any later version.
10 + % You can also redistribute it and/or modify it under the terms of the
11 + % Mozilla Public License, version 1.1 or later.
12 + %
13 + % This library is distributed in the hope that it will be useful,
14 + % but WITHOUT ANY WARRANTY; without even the implied warranty of
15 + % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 + % GNU Lesser General Public License and the GNU General Public License
17 + % for more details.
18 + %
19 + % You should have received a copy of the GNU Lesser General Public
20 + % License, of the GNU General Public License and of the Mozilla Public License
21 + % along with this library.
22 + % If not, see <http://www.gnu.org/licenses/> and
23 + % <http://www.mozilla.org/MPL/>.
24 + %
25 + % Author: Olivier Boudeville [olivier (dot) boudeville (at) esperide (dot) com]
26 +
27 +
28 +
29 + % WOOPER: Wrapper for OOP in ERlang.
30 +
31 + % See documentation at:
32 + % http://ceylan.sourceforge.net/main/documentation/wooper/
33 +
34 +
35 + % Creation date: Friday, July 6, 2007.
36 + % Author: Olivier Boudeville [olivier (dot) boudeville (at) esperide (dot) com]
37 +
38 + % Licensed under a disjunctive tri-license: MPL/GPL/LGPL, see:
39 + % http://ceylan.sourceforge.net/main/documentation/wooper/index.html#license
40 +
41 +
42 + % Provides most classical constructs: new/delete operators, remote method
43 + % invocation (RMI), polymorphism and multiple inheritance, all with state
44 + % management and in a quite efficient way (i.e. no significantly faster approach
45 + % in Erlang could be imagined by the author - before he became aware of the
46 + % existence of parse transforms).
47 +
48 + % Instances are created thanks to the new operator, which calls automatically
49 + % the relevant constructor ('construct' function).
50 +
51 + % A class C is mapped to an Erlang module, preferably named 'class_C'.
52 + %
53 + % An active object is mapped to an Erlang process.
54 + %
55 + % Methods support Remote Invocation Calls, mapped to Erlang messages.
56 + %
57 + % Inheritance is implemented thanks to a per-class method virtual table,
58 + % including the locally-defined ones and all the inherited ones.
59 + %
60 + % This table is shared among all the instances of a given class, thanks to a
61 + % singleton-like class manager process that keeps references to the virtual
62 + % table of each class.
63 + %
64 + % Instance state is maintained thanks to a per-instance attribute table, storing
65 + % all its attributes, including all the inherited ones.
66 + %
67 + % The hashtable type, defined in hashtable.erl, is used at all levels:
68 + % per-instance (for the attribute table), per-class (for the so-called virtual
69 + % table), per-node (for the class manager).
70 + %
71 + % The proplist module could be used instead.
72 +
73 + % When an exported function is called as a method (i.e. it is listed in the
74 + % wooper_method_export variable, see below) the list of parameters being
75 + % received is prefixed with the instance state (a bit like 'self' in Python):
76 + % A ! { aMethod, [1,2] } results in the calling of the 'aMethod' function
77 + % defined in the class module of A (exported thanks to wooper_method_export)
78 + % with parameters automatically given to that function being: 'CurrentStateOfA,
79 + % 1, 2' instead of '1, 2', with CurrentStateOfA being the A state variable
80 + % automatically kept in the instance WOOPER main loop.
81 + %
82 + % Hence 'aMethod' must have been defined as aMethod/3 instead of aMethod/2 (it
83 + % is indeed 'aMethod(State,X,Y) -> [..]'), whereas from the outside it is called
84 + % with only two parameters specified (state not being included).
85 +
86 +
87 + % The usual content of the '-export([XXX]).' clause in a class module should be
88 + % dispatched in:
89 + %
90 + % '-define( wooper_method_export, YYY ).', to declare methods, ex:
91 + % '-define( wooper_method_export, getAge/1, setAge/2, declareBirthday/1 ).'
92 + % Zero arity is not possible since there is at least the 'State' first
93 + % parameter. So one just increments the number of intended real
94 + % function-specific parameters in this export.
95 + % Ex: a function 'setAge' taking in input only one logical parameter, NewAge,
96 + % should actually be defined as 'setAge(State,NewAge) -> [..]' and therefore
97 + % declared as: '-define( wooper_method_export, a/1, setAge/2, b/2 ).'
98 + % Note: one should not forget, when overloading a method F/A, to specify it in
99 + % wooper_method_export, otherwise its closest ancestor method will be called
100 + % instead. In this case a warning is issued at compilation of the child class:
101 + % 'Warning: function F/A is unused.'; static methods can be declared also here.
102 + %
103 + % '-define( wooper_construct_export, new/p, new_link/p, construct/p+1, ...).'
104 + % Ex:
105 + % '-define( wooper_construct_export, new/2, new_link/2, construct/3, ...).'
106 + % to declare the appropriate construction-related functions (the 'new'
107 + % variations and the 'construct' operator), p being the number of
108 + % parameters defined in the wooper_construct_parameters variable.
109 + % Only the relevant 'construct' function has to be actually defined by the
110 + % developer: all new variations are automatically defined appropriately
111 + % (see in this file).
112 + % Declaring and implementing a toString/1 method is optional, but may be
113 + % convenient for the debugging of method implementations.
114 + %
115 + % '-export([ZZZ]).', ex: '-export([example_fun/0, f/2]).' for usual exported
116 + % functions, that are not methods.
117 + %
118 + % Note that the dispatching of functions into wooper_method_export,
119 + % wooper_construct_export and classical exports is done mainly for
120 + % self-documenting purpose (they are all just translated into the usual
121 + % export declarations).
122 +
123 +
124 +
125 + % A note about the MODULE macro:
126 + %
127 + % Its behaviour, similar to a global variable, induces issues, for example when
128 + % a process has to embody a new instance, thanks to the wooper module: ?MODULE
129 + % would then be 'wooper' instead of the one of the targeted class.
130 + %
131 + % For this reason, we shall always rely only onto the 'actual_class' of the
132 + % state_holder record (rather than on ?MODULE).
133 + %
134 + % When such a state is not available, we are before the creation of the instance
135 + % (in a *new* operator), and we are in the code path for normal instance
136 + % creation where ?MODULE can be used.
137 + %
138 + % Otherwise an embodiment is performed, in which case the class name is a
139 + % parameter, and ?MODULE shall not be used.
140 +
141 +
142 +
143 + % Regarding includes:
144 + %
145 + % The unability to export functions or types after function definitions is a
146 + % real pain when having multiple headers doing both.
147 + %
148 + % In case of problem, we split a header H.hrl into H_exports.hrl and
149 + % H_functions.hrl, and include them only in the final module to compile (as
150 + % opposed to having each module list the headers it depends on), into two
151 + % sections, first the exports, then the function definitions. This also allows
152 + % to have each relevant header included exactly once (hence, for example, no
153 + % need for include guards).
154 +
155 +
156 +
157 + % Regarding exceptions:
158 + %
159 + % User code is expected to rely only on the throw exception class, rather than
160 + % on the error or exit ones.
161 +
162 +
163 +
164 + % First exports:
165 +
166 + -include("wooper_defines_exports.hrl").
167 + -include("wooper_destruction_exports.hrl").
168 + -include("wooper_execute_exports.hrl").
169 + -include("wooper_execute_internal_exports.hrl").
170 + -include("wooper_serialisation_exports.hrl").
171 + -include("wooper_state_exports.hrl").
172 + -include("wooper_types_exports.hrl").
173 + -include("wooper_main_loop_exports.hrl").
174 + -include("wooper_for_classes.hrl").
175 +
176 +
177 + % Then function definitions:
178 +
179 + -include("wooper_classes_functions.hrl").
180 + -include("wooper_creation_functions.hrl").
181 + -include("wooper_destruction_functions.hrl").
182 + -include("wooper_execute_functions.hrl").
183 + -include("wooper_execute_internal_functions.hrl").
184 + -include("wooper_main_loop_functions.hrl").
185 + -include("wooper_serialisation_functions.hrl").
186 + -include("wooper_state_functions.hrl").
187 +
188 + % Nothing needed for static methods.
  @@ -0,0 +1,42 @@
1 + % Copyright (C) 2003-2019 Olivier Boudeville
2 + %
3 + % This file is part of the Ceylan-WOOPER library.
4 + %
5 + % This library is free software: you can redistribute it and/or modify
6 + % it under the terms of the GNU Lesser General Public License or
7 + % the GNU General Public License, as they are published by the Free Software
8 + % Foundation, either version 3 of these Licenses, or (at your option)
9 + % any later version.
10 + % You can also redistribute it and/or modify it under the terms of the
11 + % Mozilla Public License, version 1.1 or later.
12 + %
13 + % This library is distributed in the hope that it will be useful,
14 + % but WITHOUT ANY WARRANTY; without even the implied warranty of
15 + % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 + % GNU Lesser General Public License and the GNU General Public License
17 + % for more details.
18 + %
19 + % You should have received a copy of the GNU Lesser General Public
20 + % License, of the GNU General Public License and of the Mozilla Public License
21 + % along with this library.
22 + % If not, see <http://www.gnu.org/licenses/> and
23 + % <http://www.mozilla.org/MPL/>.
24 + %
25 + % Author: Olivier Boudeville [olivier (dot) boudeville (at) esperide (dot) com]
26 +
27 +
28 + % Header sharing defines for the WOOPER class manager.
29 +
30 + % See documentation at:
31 + % http://ceylan.sourceforge.net/main/documentation/wooper/
32 +
33 +
34 + % Creation date: Friday, July 12, 2007.
35 + % Author: Olivier Boudeville [olivier (dot) boudeville (at) esperide (dot) com]
36 +
37 + % Licensed under a disjunctive tri-license: MPL/GPL/LGPL, see:
38 + % http://ceylan.sourceforge.net/main/documentation/wooper/index.html#license
39 +
40 +
41 + % The class manager name that will be registered:
42 + -define( wooper_class_manager_name, wooper_class_manager ).
  @@ -0,0 +1,76 @@
1 + % Copyright (C) 2003-2019 Olivier Boudeville
2 + %
3 + % This file is part of the Ceylan-WOOPER library.
4 + %
5 + % This library is free software: you can redistribute it and/or modify
6 + % it under the terms of the GNU Lesser General Public License or
7 + % the GNU General Public License, as they are published by the Free Software
8 + % Foundation, either version 3 of these Licenses, or (at your option)
9 + % any later version.
10 + % You can also redistribute it and/or modify it under the terms of the
11 + % Mozilla Public License, version 1.1 or later.
12 + %
13 + % This library is distributed in the hope that it will be useful,
14 + % but WITHOUT ANY WARRANTY; without even the implied warranty of
15 + % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 + % GNU Lesser General Public License and the GNU General Public License
17 + % for more details.
18 + %
19 + % You should have received a copy of the GNU Lesser General Public
20 + % License, of the GNU General Public License and of the Mozilla Public License
21 + % along with this library.
22 + % If not, see <http://www.gnu.org/licenses/> and
23 + % <http://www.mozilla.org/MPL/>.
24 + %
25 + % Author: Olivier Boudeville [olivier (dot) boudeville (at) esperide (dot) com]
26 +
27 +
28 + % Modular WOOPER header gathering the class-related primitives (function
29 + % definitions).
30 +
31 +
32 + % Note: functions below (ex: getClassname/1) are "verbatim" methods: rather than
33 + % being generated through a parse-transform (which would bring no added value),
34 + % it is actually more convenient to inject their code thanks to a header file.
35 + % However these verbatim methods shall not be considered as built-in, as we want
36 + % to have them registered (known of the WOOPER parse transforms) as methods (ex:
37 + % so that they are themselves transformed, since they use method terminators).
38 +
39 + % Request returning the classname of the instance.
40 + %
41 + % Always accurate, in all constructors, methods and destructors.
42 + %
43 + -spec getClassname( wooper:state() ) -> const_request_return( classname() ).
44 + getClassname( State ) ->
45 + wooper:const_return_result( State#state_holder.actual_class ).
46 +
47 +
48 +
49 + % Method that returns the (direct) superclasses of the instance.
50 + %
51 + % Always accurate, in all constructors, methods and destructors.
52 + %
53 + -spec getSuperclasses( wooper:state() ) ->
54 + const_request_return( [ classname() ] ).
55 + getSuperclasses( State ) ->
56 + ActualModule = State#state_holder.actual_class,
57 + SuperClasses = ActualModule:get_superclasses(),
58 + wooper:const_return_result( SuperClasses ).
59 +
60 +
61 +
62 + -ifdef(wooper_debug).
63 +
64 +
65 + % Returns a full textual description of this instance, including its state and
66 + % virtual table.
67 + %
68 + % This is a method for debug purpose, only activated if wooper_debug is defined.
69 + %
70 + -spec wooper_get_instance_description( wooper:state() ) ->
71 + const_request_return( text_utils:ustring() ).
72 + wooper_get_instance_description( State ) ->
73 + wooper:const_return_result( wooper:instance_to_string( State ) ).
74 +
75 +
76 + -endif. % wooper_debug
  @@ -0,0 +1,1045 @@
1 + % Copyright (C) 2003-2019 Olivier Boudeville
2 + %
3 + % This file is part of the Ceylan-WOOPER library.
4 + %
5 + % This library is free software: you can redistribute it and/or modify
6 + % it under the terms of the GNU Lesser General Public License or
7 + % the GNU General Public License, as they are published by the Free Software
8 + % Foundation, either version 3 of these Licenses, or (at your option)
9 + % any later version.
10 + % You can also redistribute it and/or modify it under the terms of the
11 + % Mozilla Public License, version 1.1 or later.
12 + %
13 + % This library is distributed in the hope that it will be useful,
14 + % but WITHOUT ANY WARRANTY; without even the implied warranty of
15 + % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 + % GNU Lesser General Public License and the GNU General Public License
17 + % for more details.
18 + %
19 + % You should have received a copy of the GNU Lesser General Public
20 + % License, of the GNU General Public License and of the Mozilla Public License
21 + % along with this library.
22 + % If not, see <http://www.gnu.org/licenses/> and
23 + % <http://www.mozilla.org/MPL/>.
24 + %
25 + % Author: Olivier Boudeville [olivier (dot) boudeville (at) esperide (dot) com]
26 +
27 +
28 + %% IMPORTANT NOTE
29 + %%
30 + %% This file is not used anymore. It has been replaced as a whole by the WOOPER
31 + %% parse transform. It is staged for deletion.
32 +
33 +
34 +
35 + % Modular WOOPER header gathering the primitives to manage the creation of
36 + % instances.
37 +
38 +
39 +
40 + % The creation of an instance of a WOOPER class can be:
41 + %
42 + % - either non-blocking or synchronous (and, if synchronous, with or without a
43 + % time-out)
44 + %
45 + % - either not linked or linked to the current process
46 + %
47 + % - either local (on the current node) or remote (on another node)
48 +
49 +
50 +
51 + % Following construction variations are always declared, for a constructor
52 + % expected to take N base parameters:
53 + % new/N, new_link/N, synchronous_new/N, synchronous_new_link/N
54 +
55 + % If use_synchronous_timed_new is defined, WOOPER adds:
56 + % synchronous_timed_new/N, synchronous_timed_new_link/N
57 +
58 + % If use_remote_new is defined, WOOPER adds:
59 + % remote_new/N+1, remote_new_link/N+1, remote_synchronous_new/N+1,
60 + % remote_synchronous_new_link/N+1, remote_synchronisable_new_link/N+1.
61 +
62 + % Finally, if use_synchronous_timed_new *and* use_remote_new are defined,
63 + % WOOPER adds these timed operations:
64 + % remote_synchronous_timed_new/N+1, remote_synchronous_timed_new_link/N+1.
65 +
66 + % Therefore for a template for a full-blown declaration would be:
67 + % (in the next block, just search and replace with your text editor A with N,
68 + % and B with N+1)
69 +
70 +
71 + % Declaring all variations of WOOPER standard life-cycle operations:
72 + %
73 + %-define( wooper_construct_export, new/A, new_link/A,
74 + % synchronous_new/A, synchronous_new_link/A,
75 + % synchronous_timed_new/A, synchronous_timed_new_link/A,
76 + % remote_new/B, remote_new_link/B, remote_synchronous_new/B,
77 + % remote_synchronous_new_link/B, remote_synchronisable_new_link/B,
78 + % remote_synchronous_timed_new/B, remote_synchronous_timed_new_link/B,
79 + % construct/B, destruct/1 ).
80 +
81 +
82 + % Note: destruct/1 can be removed from the export list above if no specific
83 + % destructor is to be defined.
84 +
85 +
86 +
87 + % There are construction operators that just take the construction parameters,
88 + % ?wooper_construct_parameters (like new/N), and other operators that take
89 + % an additional parameter, the target node (like remote_new/N+1).
90 + %
91 + % As wooper_construct_parameters can be void (i.e. declared as
92 + % '-define(wooper_construct_parameters,).'), the declaration 'new(
93 + % ?wooper_construct_parameters )' would be correct, whereas 'remote_new(
94 + % Node, ?wooper_construct_parameters )' would result in the incorrect syntax
95 + % 'remote_new( Node, )'.
96 + %
97 + % A solution could be, depending on wooper_construct_parameters being void or
98 + % not, to define either 'remote_new( Node )' (if void) or 'remote_new(
99 + % Node,?wooper_construct_parameters )' (if not void).
100 + %
101 + % However the Erlang macros do not seem to support tests based on their value
102 + % (we can only test whether they are defined or not), thus the following
103 + % convention has been used:
104 +
105 + % wooper_construct_parameters should be defined if and only if there is at least
106 + % one parameter to be declared.
107 + %
108 + % Therefore, in the case of a constructor taking two parameters, X and Y, we
109 + % will have:
110 + %
111 + % -define( wooper_construct_parameters, X, Y ).
112 + % ...
113 + % construct( State, ?wooper_construct_parameters ) ->
114 + % ...
115 + %
116 + % whereas in the case of a constructor taking no parameter, we will have simply:
117 + %
118 + % ...
119 + % construct( State ) ->
120 + % ...
121 + %
122 +
123 + % i.e. there will be in this case no: '-define(wooper_construct_parameters,)'.
124 +
125 +
126 + % No specification can be provided for new operators, due to their
127 + % class-specific arities.
128 +
129 +
130 +
131 + % Uncomment to activate synchronous, timed constructions:
132 + %
133 + % (yes, we want to enable them)
134 + %
135 + -define(use_synchronous_timed_new,).
136 +
137 +
138 +
139 + % Uncomment to activate remote new constructions:
140 + %
141 + % (yes, we want to enable them)
142 + %
143 + -define(use_remote_new,).
144 +
145 +
146 +
147 +
148 + % First case: wooper_construct_parameters is defined:
149 +
150 + -ifdef(wooper_construct_parameters).
151 +
152 +
153 +
154 + % Spawns a new instance for this class, using specified parameters to construct
155 + % it.
156 + %
157 + % Returns the PID of the newly created instance.
158 + %
159 + % Creation is asynchronous: new returns as soon as the creation is triggered,
160 + % without waiting for it to complete.
161 + %
162 + %% new( ?wooper_construct_parameters ) ->
163 +
164 + %% %trace_utils:debug_fmt("new operator: spawning ~w:wooper_construct_and_run "
165 + %% % "with parameters ~w.~n", [ ?MODULE, [ ?wooper_construct_parameters ] ] ),
166 +
167 + %% spawn( fun() ->
168 + %% wooper_construct_and_run( [ ?wooper_construct_parameters ] )
169 + %% end ).
170 +
171 +
172 +
173 + % Spawns a new instance for this class and links it to the current process,
174 + % using specified parameters to construct it.
175 + %
176 + % Returns the PID of the newly created and linked instance.
177 + %
178 + % Creation is asynchronous: new_link returns as soon as the creation is
179 + % triggered, without waiting for it to complete.
180 + %
181 + %% new_link( ?wooper_construct_parameters ) ->
182 +
183 + %% spawn_link( fun() ->
184 + %% wooper_construct_and_run(
185 + %% [ ?wooper_construct_parameters ] )
186 + %% end ).
187 +
188 +
189 +
190 + % Spawns a new instance for this class, using specified parameters to construct
191 + % it.
192 + %
193 + % Returns the PID of the newly created instance.
194 + %
195 + % Creation is synchronous: synchronous_new will return only when the created
196 + % process reports it is up and running.
197 + %
198 + %% synchronous_new( ?wooper_construct_parameters ) ->
199 +
200 + %% %trace_utils:debug_fmt("synchronous_new operator: spawning "
201 + %% % "~w:wooper_construct_and_run with parameters ~w.~n",
202 + %% % [ ?MODULE, [ ?wooper_construct_parameters ] ] ),
203 +
204 + %% CreatorPid = self(),
205 +
206 + %% SpawnedPid = spawn( fun() ->
207 + %% wooper_construct_and_run_synchronous(
208 + %% [ ?wooper_construct_parameters ], CreatorPid )
209 + %% end ),
210 +
211 + %% % Blocks until the spawned process answers:
212 + %% %
213 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
214 + %% % waited for)
215 + %% %
216 + %% receive
217 +
218 + %% { spawn_successful, SpawnedPid } ->
219 + %% SpawnedPid
220 +
221 + %% end.
222 +
223 +
224 +
225 + % Spawns a new instance for this class and links it to the current process,
226 + % using specified parameters to construct it.
227 + %
228 + % Returns the PID of the newly created instance.
229 + %
230 + % Creation is synchronous: synchronous_new_link will return only when the
231 + % created process reports it is up and running.
232 + %
233 + %% synchronous_new_link( ?wooper_construct_parameters ) ->
234 +
235 + %% %trace_utils:debug_fmt( "synchronous_new_link for ~s with parameters:~n~p.~n",
236 + %% % [ ?MODULE, [ ?wooper_construct_parameters ] ] ),
237 +
238 + %% CreatorPid = self(),
239 +
240 + %% SpawnedPid = spawn_link( fun() ->
241 + %% wooper_construct_and_run_synchronous(
242 + %% [ ?wooper_construct_parameters ],
243 + %% CreatorPid )
244 + %% end ),
245 +
246 + %% % Blocks until the spawned process answers:
247 + %% %
248 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
249 + %% % waited for)
250 + %% %
251 + %% receive
252 +
253 + %% { spawn_successful, SpawnedPid } ->
254 + %% %trace_utils:debug_fmt( "synchronous_new_link: spawned ~w.~n", [SpawnedPid] ),
255 + %% SpawnedPid
256 +
257 + %% end.
258 +
259 +
260 +
261 +
262 +
263 +
264 + -ifdef(use_synchronous_timed_new).
265 +
266 +
267 +
268 +
269 + % Spawns a new instance for this class, using specified parameters to construct
270 + % it.
271 + %
272 + % Returns the PID of the newly created instance, or the time_out atom.
273 + %
274 + % Creation is synchronous: synchronous_timed_new will return only when the
275 + % created process reports it is up and running, or when a time-out occurs.
276 + %
277 + %-spec synchronous_timed_new() -> pid().
278 + %% synchronous_timed_new( ?wooper_construct_parameters ) ->
279 +
280 + %% CreatorPid = self(),
281 +
282 + %% SpawnedPid = spawn(
283 + %% fun() ->
284 + %% wooper_construct_and_run_synchronous(
285 + %% [ ?wooper_construct_parameters ], CreatorPid )
286 + %% end ),
287 +
288 + %% % Blocks until the spawned process answers or a time-out occurs:
289 + %% %
290 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
291 + %% % waited for)
292 + %% %
293 + %% receive
294 +
295 + %% { spawn_successful, SpawnedPid } ->
296 + %% SpawnedPid
297 +
298 + %% after ?synchronous_time_out ->
299 +
300 + %% throw( { synchronous_time_out, ?MODULE } )
301 +
302 + %% end.
303 +
304 +
305 +
306 + % Spawns a new instance for this class, and links it to the current process,
307 + % using specified parameters to construct it.
308 + %
309 + % Returns the PID of the newly created instance, or the time_out atom.
310 + %
311 + % Creation is synchronous: synchronous_timed_new_link will return only when the
312 + % created process reports it is up and running, or when a time-out occurs.
313 + %
314 + %% synchronous_timed_new_link( ?wooper_construct_parameters ) ->
315 +
316 + %% CreatorPid = self(),
317 +
318 + %% SpawnedPid = spawn_link( fun() ->
319 + %% wooper_construct_and_run_synchronous(
320 + %% [ ?wooper_construct_parameters ],
321 + %% CreatorPid )
322 + %% end ),
323 +
324 + %% % Blocks until the spawned process answers or a time-out occurs:
325 + %% %
326 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
327 + %% % waited for)
328 + %% %
329 + %% receive
330 +
331 + %% { spawn_successful, SpawnedPid } ->
332 + %% SpawnedPid
333 +
334 + %% after ?synchronous_time_out ->
335 +
336 + %% throw( { synchronous_linked_time_out, ?MODULE } )
337 +
338 + %% end.
339 +
340 +
341 +
342 + -endif. % use_synchronous_timed_new
343 +
344 +
345 +
346 +
347 + % If use_remote_new is defined, following construction variations will be
348 + % automatically defined (and thus class implementor will have to declare them):
349 + %
350 + % - remote_new
351 + % - remote_new_link
352 + % - remote_synchronous_new
353 + % - remote_synchronous_new_link
354 + % - remote_synchronisable_new_link
355 + % - synchronous_timed_new
356 + %
357 + % The arity of these remote operators is equal to the one of their local
358 + % counterparts plus one: if having new/N, then we have remote_new/N+1.
359 +
360 +
361 +
362 + -ifdef(use_remote_new).
363 +
364 +
365 + % Spawns a new instance for this class on specified interconnected node, using
366 + % specified parameters to construct it.
367 + %
368 + % If Node does not exist, a useless pid is returned.
369 + %
370 + % Returns the PID of the newly created instance.
371 + %
372 + % Creation is asynchronous: remote_new returns as soon as the creation is
373 + % triggered, without waiting for it to complete.
374 + %
375 + %% remote_new( Node, ?wooper_construct_parameters ) ->
376 +
377 + %% spawn( Node, fun() ->
378 + %% wooper_construct_and_run(
379 + %% [ ?wooper_construct_parameters ] )
380 + %% end ).
381 +
382 +
383 +
384 + % Spawns a new instance for this class on specified interconnected node, and
385 + % links it to the current process, using specified parameters to construct it.
386 + %
387 + % If Node does not exist, a useless pid is returned.
388 + %
389 + % Returns the PID of the newly created instance.
390 + %
391 + % Creation is asynchronous: remote_new_link returns as soon as the creation is
392 + % triggered, without waiting for it to complete.
393 + %
394 + %% remote_new_link( Node, ?wooper_construct_parameters ) ->
395 +
396 + %% spawn_link( Node, fun() ->
397 + %% wooper_construct_and_run(
398 + %% [ ?wooper_construct_parameters ] )
399 + %% end ).
400 +
401 +
402 +
403 + % Spawns a new instance for this class on specified interconnected node, using
404 + % specified parameters to construct it.
405 + %
406 + % Returns the PID of the newly created instance.
407 + %
408 + % Creation is synchronous: remote_synchronous_new will return only when the
409 + % created process reports it is up and running.
410 + %
411 + %% remote_synchronous_new( Node, ?wooper_construct_parameters ) ->
412 +
413 + %% %trace_utils:debug_fmt( "remote_synchronous_new operator: "
414 + %% % "spawning ~w:wooper_construct_and_run_synchronous "
415 + %% % "with parameters ~w.~n", [ ?MODULE, [ ?wooper_construct_parameters ] ] ),
416 + %% %timer:sleep(200),
417 +
418 + %% CreatorPid = self(),
419 +
420 + %% SpawnedPid = spawn( Node, fun() ->
421 + %% wooper_construct_and_run_synchronous(
422 + %% [ ?wooper_construct_parameters ],
423 + %% CreatorPid )
424 + %% end ),
425 +
426 + %% % Blocks until the spawned process answers:
427 + %% %
428 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
429 + %% % waited for)
430 + %% %
431 + %% receive
432 +
433 + %% { spawn_successful, SpawnedPid } ->
434 + %% SpawnedPid
435 +
436 + %% end.
437 +
438 +
439 +
440 + % Spawns a new instance for this class on specified interconnected node and
441 + % links it to the current process, using specified parameters to construct it.
442 + %
443 + % Returns the PID of the newly created instance.
444 + %
445 + % Creation is synchronous: remote_synchronous_new_link will return only when the
446 + % created process reports it is up and running.
447 + %
448 + %% remote_synchronous_new_link( Node, ?wooper_construct_parameters ) ->
449 +
450 + %% %trace_utils:debug_fmt( "remote_synchronous_new_link operator: "
451 + %% % "spawning ~w:wooper_construct_and_run_synchronous "
452 + %% % "with parameters ~w.~n", [ ?MODULE, [ ?wooper_construct_parameters ] ] ),
453 + %% %timer:sleep(200),
454 +
455 + %% CreatorPid = self(),
456 +
457 + %% SpawnedPid = spawn_link( Node, fun() ->
458 + %% wooper_construct_and_run_synchronous(
459 + %% [ ?wooper_construct_parameters ],
460 + %% CreatorPid )
461 + %% end ),
462 +
463 + %% % Blocks until the spawned process answers:
464 + %% %
465 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
466 + %% % waited for)
467 + %% %
468 + %% receive
469 +
470 + %% { spawn_successful, SpawnedPid } ->
471 + %% SpawnedPid
472 +
473 + %% end.
474 +
475 +
476 +
477 + % Spawns a new instance for this class on specified interconnected node and
478 + % links it to the current process, using specified parameters to construct it.
479 + %
480 + % Returns the PID of the newly created instance.
481 + %
482 + % Creation is asynchronous (the PID is directly returned), however a
483 + % {spawn_successful,SpawnedPid} message will be received once (if ever) the
484 + % instance is up and running. This allows to perform the actual instance
485 + % creations in parallel, by waiting bulks of creations.
486 + %
487 + %% remote_synchronisable_new_link( Node, ?wooper_construct_parameters ) ->
488 +
489 + %% %trace_utils:debug_fmt( "remote_synchronisable_new_link operator: "
490 + %% % "spawning ~w:wooper_construct_and_run_synchronous "
491 + %% % "with parameters ~w.~n", [ ?MODULE, [ ?wooper_construct_parameters ] ] ),
492 + %% %timer:sleep(200),
493 +
494 + %% CreatorPid = self(),
495 +
496 + %% spawn_link( Node, fun() ->
497 + %% wooper_construct_and_run_synchronous(
498 + %% [ ?wooper_construct_parameters ],
499 + %% CreatorPid )
500 + %% end ).
501 +
502 +
503 +
504 + -ifdef(use_synchronous_timed_new).
505 +
506 +
507 + % Spawns a new instance for this class on specified interconnected node, using
508 + % specified parameters to construct it.
509 + %
510 + % Returns the PID of the newly created instance, or the time_out atom.
511 + %
512 + % Creation is synchronous: remote_synchronous_timed_new will return
513 + % only when the created process reports it is up and running, or when
514 + % a time-out occurs.
515 + %
516 + %% remote_synchronous_timed_new( Node, ?wooper_construct_parameters ) ->
517 +
518 + %% %trace_utils:debug_fmt( "remote_synchronous_timed_new operator: "
519 + %% % "spawning ~w:wooper_construct_and_run_synchronous "
520 + %% % "with parameters ~w.~n", [ ?MODULE, [ ?wooper_construct_parameters ] ] ),
521 + %% %timer:sleep(200),
522 +
523 + %% CreatorPid = self(),
524 +
525 + %% SpawnedPid = spawn( Node, fun() ->
526 + %% wooper_construct_and_run_synchronous(
527 + %% [ ?wooper_construct_parameters ],
528 + %% CreatorPid )
529 + %% end ),
530 +
531 + %% % Blocks until the spawned process answers or a time-out occurs:
532 + %% %
533 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
534 + %% % waited for)
535 + %% %
536 + %% receive
537 +
538 + %% { spawn_successful, SpawnedPid } ->
539 + %% SpawnedPid
540 +
541 + %% after ?synchronous_time_out ->
542 +
543 + %% throw( { remote_synchronous_time_out, Node, ?MODULE } )
544 +
545 + %% end.
546 +
547 +
548 +
549 + % Spawns a new instance for this class on specified interconnected node, and
550 + % links it to the current process, using specified parameters to construct it.
551 + %
552 + % Returns the PID of the newly created instance, or the time_out atom.
553 + %
554 + % Creation is synchronous: remote_synchronous_timed_new_link will return only
555 + % when the created process reports it is up and running, or when a time-out
556 + % occurs.
557 + %
558 + %% remote_synchronous_timed_new_link( Node, ?wooper_construct_parameters ) ->
559 +
560 + %% %trace_utils:debug_fmt( "remote_synchronous_timed_new_link operator: "
561 + %% % "spawning ~w:wooper_construct_and_run_synchronous "
562 + %% % "with parameters ~w on node ~w from node ~w.~n",
563 + %% % [ ?MODULE, [ ?wooper_construct_parameters ] , Node, node() ] ),
564 +
565 + %% CreatorPid = self(),
566 +
567 + %% SpawnedPid = spawn_link( Node, fun() ->
568 + %% wooper_construct_and_run_synchronous(
569 + %% [ ?wooper_construct_parameters ],
570 + %% CreatorPid )
571 + %% end ),
572 +
573 + %% % Blocks until the spawned process answers or a time-out occurs:
574 + %% %
575 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
576 + %% % waited for)
577 + %% %
578 + %% receive
579 +
580 + %% { spawn_successful, SpawnedPid } ->
581 + %% %trace_utils:debug_fmt( "remote_synchronous_timed_new_link: returning ~w.~n",
582 + %% % [ SpawnedPid ] ),
583 + %% SpawnedPid
584 +
585 + %% after ?synchronous_time_out ->
586 +
587 + %% io:format( "(remote_synchronous_timed_new_link: throwing time-out "
588 + %% "on node ~p for module ~p after ~p milliseconds)~n",
589 + %% [ Node, ?MODULE, ?synchronous_time_out ] ),
590 +
591 + %% throw( { remote_synchronous_linked_time_out, Node, ?MODULE } )
592 +
593 + %% end.
594 +
595 +
596 +
597 + -endif. % use_synchronous_timed_new
598 +
599 + -endif. % use_remote_new
600 +
601 +
602 +
603 +
604 +
605 +
606 +
607 + -else. % -ifdef(wooper_construct_parameters).
608 +
609 +
610 +
611 + % Second case: wooper_construct_parameters is *not* defined:
612 + % No argument, thus specs can be defined.
613 +
614 +
615 + % Spawns a new instance for this class.
616 + % Returns the PID of the newly created instance.
617 + %
618 + % Creation is asynchronous: new returns as soon as the creation is triggered,
619 + % without waiting for it to complete.
620 + %
621 + %% -spec new() -> pid().
622 + %% new() ->
623 +
624 + %% %trace_utils:debug_fmt("new operator: spawning ~w:wooper_construct_and_run "
625 + %% % "with no parameter.~n", [ ?MODULE ] ),
626 +
627 + %% spawn( fun() ->
628 + %% wooper_construct_and_run( _ConstructParams=[] )
629 + %% end ).
630 +
631 +
632 +
633 + % Spawns a new instance for this class and links it to the current process.
634 + %
635 + % Returns the PID of the newly created and linked instance.
636 + %
637 + % Creation is asynchronous: new_link returns as soon as the creation is
638 + % triggered, without waiting for it to complete.
639 + %
640 + %% -spec new_link() -> pid().
641 + %% new_link() ->
642 +
643 + %% spawn_link( fun() ->
644 + %% wooper_construct_and_run( _ConstructParams=[] )
645 + %% end ).
646 +
647 +
648 +
649 + % Spawns a new instance for this class.
650 + %
651 + % Returns the PID of the newly created instance.
652 + %
653 + % Creation is synchronous: synchronous_new will return only when the created
654 + % process reports it is up and running.
655 + %
656 + %% -spec synchronous_new() -> pid().
657 + %% synchronous_new() ->
658 +
659 + %% %trace_utils:debug_fmt("synchronous_new operator: spawning ~w "
660 + %% % "with no parameter.~n", [ ?MODULE ] ),
661 +
662 + %% CreatorPid = self(),
663 +
664 + %% SpawnedPid = spawn( fun() ->
665 + %% wooper_construct_and_run_synchronous(
666 + %% _ConstructParams=[], CreatorPid )
667 + %% end ),
668 +
669 + %% % Blocks until the spawned process answers:
670 + %% receive
671 +
672 + %% { spawn_successful, SpawnedPid } ->
673 + %% SpawnedPid
674 +
675 + %% end.
676 +
677 +
678 +
679 + % Spawns a new instance for this class and links it to the current process.
680 + % Returns the PID of the newly created instance.
681 + %
682 + % Creation is synchronous: synchronous_new_link will return only when the
683 + % created process reports it is up and running.
684 + %
685 + %% -spec synchronous_new_link() -> pid().
686 + %% synchronous_new_link() ->
687 +
688 + %% CreatorPid = self(),
689 +
690 + %% SpawnedPid = spawn_link( fun() ->
691 + %% wooper_construct_and_run_synchronous(
692 + %% _ConstructParams=[], CreatorPid )
693 + %% end ),
694 +
695 + %% % Blocks until the spawned process answers:
696 + %% %
697 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
698 + %% % waited for)
699 + %% %
700 + %% receive
701 +
702 + %% { spawn_successful, SpawnedPid } ->
703 + %% SpawnedPid
704 +
705 + %% end.
706 +
707 +
708 +
709 + -ifdef(use_synchronous_timed_new).
710 +
711 +
712 +
713 +
714 + % Spawns a new instance for this class.
715 + %
716 + % Returns the PID of the newly created instance, or the time_out atom.
717 + %
718 + % Creation is synchronous: synchronous_timed_new will return only when the
719 + % created process reports it is up and running, or when a time-out occurs.
720 + %
721 + %% -spec synchronous_timed_new() -> pid().
722 + %% synchronous_timed_new() ->
723 +
724 + %% CreatorPid = self(),
725 +
726 + %% SpawnedPid = spawn( fun() ->
727 + %% wooper_construct_and_run_synchronous(
728 + %% _ConstructParams=[], CreatorPid )
729 + %% end ),
730 +
731 + %% % Blocks until the spawned process answers or a time-out occurs:
732 + %% receive
733 +
734 + %% { spawn_successful, SpawnedPid } ->
735 + %% SpawnedPid
736 +
737 + %% after ?synchronous_time_out ->
738 +
739 + %% throw( { synchronous_time_out, ?MODULE } )
740 +
741 + %% end.
742 +
743 +
744 +
745 + % Spawns a new instance for this class, and links it to the current process.
746 + %
747 + % Returns the PID of the newly created instance, or the time_out atom.
748 + %
749 + % Creation is synchronous: synchronous_timed_new will return only when the
750 + % created process reports it is up and running, or when a time-out occurs.
751 + %
752 + %% -spec synchronous_timed_new_link() -> pid().
753 + %% synchronous_timed_new_link() ->
754 +
755 + %% CreatorPid = self(),
756 +
757 + %% SpawnedPid = spawn_link( fun() ->
758 + %% wooper_construct_and_run_synchronous(
759 + %% _ConstructParams=[], CreatorPid )
760 + %% end ),
761 +
762 + %% % Blocks until the spawned process answers or a time-out occurs:
763 + %% receive
764 +
765 + %% { spawn_successful, SpawnedPid } ->
766 + %% SpawnedPid
767 +
768 + %% after ?synchronous_time_out ->
769 +
770 + %% throw( { synchronous_linked_time_out, ?MODULE } )
771 +
772 + %% end.
773 +
774 +
775 +
776 + -endif. % use_synchronous_timed_new
777 +
778 +
779 +
780 + % If use_remote_new is defined, following construction variations will be
781 + % automatically defined (thus class implementor will have to declare them):
782 + %
783 + % - remote_new
784 + % - remote_new_link
785 + % - remote_synchronous_new
786 + % - remote_synchronous_new_link
787 + % - synchronous_timed_new
788 + %
789 + % The arity of these remote operators is equal to the one of their local
790 + % counterparts plus one: if having new/N, then having remote_new/N+1.
791 +
792 +
793 +
794 +
795 + -ifdef(use_remote_new).
796 +
797 +
798 +
799 + % Spawns a new instance for this class on specified interconnected node.
800 + %
801 + % If Node does not exist, a useless pid is returned.
802 + %
803 + % Returns the PID of the newly created instance.
804 + %
805 + % Creation is asynchronous: remote_new returns as soon as the creation is
806 + % triggered, without waiting for it to complete.
807 + %
808 + %% -spec remote_new( net_utils:node_name() ) -> pid().
809 + %% remote_new( Node ) ->
810 + %% spawn( Node, fun() ->
811 + %% wooper_construct_and_run( _ConstructParams=[] )
812 + %% end ).
813 +
814 +
815 +
816 + % Spawns a new instance for this class on specified interconnected node, and
817 + % links it to the current process.
818 + %
819 + % If Node does not exist, a useless pid is returned.
820 + %
821 + % Returns the PID of the newly created instance.
822 + %
823 + % Creation is asynchronous: remote_new_link returns as soon as the creation is
824 + % triggered, without waiting for it to complete.
825 + %
826 + %% -spec remote_new_link( net_utils:node_name() ) -> pid().
827 + %% remote_new_link( Node ) ->
828 + %% spawn_link( Node, fun() ->
829 + %% wooper_construct_and_run( _ConstructParams=[] )
830 + %% end ).
831 +
832 +
833 +
834 + % Spawns a new instance for this class on specified interconnected node.
835 + %
836 + % Returns the PID of the newly created instance.
837 + %
838 + % Creation is synchronous: remote_synchronous_new will return only when the
839 + % created process reports it is up and running.
840 + %
841 + %% -spec remote_synchronous_new( net_utils:node_name() ) -> pid().
842 + %% remote_synchronous_new( Node ) ->
843 +
844 + %% %trace_utils:debug_fmt("synchronous_new operator: spawning ~w "
845 + %% % "with no parameter.~n", [ ?MODULE ]),
846 +
847 + %% CreatorPid = self(),
848 +
849 + %% SpawnedPid = spawn( Node,
850 + %% fun() ->
851 + %% wooper_construct_and_run_synchronous(
852 + %% _ConstructParams=[], CreatorPid )
853 + %% end ),
854 +
855 + %% % Blocks until the spawned process answers:
856 + %% %
857 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
858 + %% % waited for)
859 + %% %
860 + %% receive
861 +
862 + %% { spawn_successful, SpawnedPid } ->
863 + %% SpawnedPid
864 +
865 + %% end.
866 +
867 +
868 +
869 + % Spawns a new instance for this class on specified interconnected node and
870 + % links it to the current process.
871 + %
872 + % Returns the PID of the newly created instance.
873 + %
874 + % Creation is synchronous: remote_synchronous_new_link will return only when the
875 + % created process reports it is up and running.
876 + %
877 + %% -spec remote_synchronous_new_link( net_utils:node_name() ) -> pid().
878 + %% remote_synchronous_new_link( Node ) ->
879 +
880 + %% CreatorPid = self(),
881 +
882 + %% SpawnedPid = spawn_link( Node, fun() ->
883 + %% wooper_construct_and_run_synchronous(
884 + %% _ConstructParams=[], CreatorPid )
885 + %% end ),
886 +
887 + %% % Blocks until the spawned process answers:
888 + %% %
889 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
890 + %% % waited for)
891 + %% %
892 + %% receive
893 +
894 + %% { spawn_successful, SpawnedPid } ->
895 + %% SpawnedPid
896 +
897 + %% end.
898 +
899 +
900 +
901 + % Spawns a new instance for this class on specified interconnected node and
902 + % links it to the current process, using specified parameters to construct it.
903 + %
904 + % Returns the PID of the newly created instance.
905 + %
906 + % Creation is asynchronous (the PID is directly returned), however a {
907 + % spawn_successful, SpawnedPid } message will be received once (if ever) the
908 + % instance is up and running.
909 + %
910 + % This allows to perform the actual instance creations in parallel, by waiting
911 + % bulks of creations.
912 + %
913 + %% remote_synchronisable_new_link( Node ) ->
914 +
915 + %% %trace_utils:debug_fmt( "remote_synchronisable_new_link operator: "
916 + %% % "spawning ~w:wooper_construct_and_run_synchronous "
917 + %% % "with parameters ~w.~n", [ ?MODULE, [ ?wooper_construct_parameters ] ] ),
918 + %% %timer:sleep(200),
919 +
920 + %% CreatorPid = self(),
921 +
922 + %% spawn_link( Node, fun() ->
923 + %% wooper_construct_and_run_synchronous(
924 + %% _ConstructParams=[], CreatorPid )
925 + %% end ).
926 +
927 +
928 +
929 + -ifdef(use_synchronous_timed_new).
930 +
931 +
932 + % Spawns a new instance for this class on specified interconnected node.
933 + %
934 + % Returns the PID of the newly created instance, or the time_out atom.
935 + %
936 + % Creation is synchronous: remote_synchronous_timed_new will return only when
937 + % the created process reports it is up and running, or when a time-out occurs.
938 + %
939 + %% -spec remote_synchronous_timed_new( net_utils:node_name() ) -> pid().
940 + %% remote_synchronous_timed_new( Node ) ->
941 +
942 + %% CreatorPid = self(),
943 +
944 + %% SpawnedPid = spawn( Node, fun() ->
945 + %% wooper_construct_and_run_synchronous(
946 + %% _ConstructParams=[], CreatorPid )
947 + %% end ),
948 +
949 + %% % Blocks until the spawned process answers or a time-out occurs:
950 + %% %
951 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
952 + %% % waited for)
953 + %% %
954 + %% receive
955 +
956 + %% { spawn_successful, SpawnedPid } ->
957 + %% SpawnedPid
958 +
959 + %% after ?synchronous_time_out ->
960 +
961 + %% throw( { remote_synchronous_time_out, Node, ?MODULE } )
962 +
963 + %% end.
964 +
965 +
966 +
967 + % Spawns a new instance for this class on specified interconnected node, and
968 + % links it to the current process.
969 + %
970 + % Returns the PID of the newly created instance, or the time_out atom.
971 + %
972 + % Creation is synchronous: remote_synchronous_timed_new_link will return only
973 + % when the created process reports it is up and running, or when a time-out
974 + % occurs.
975 + %
976 + %% -spec remote_synchronous_timed_new_link( net_utils:node_name() ) -> pid().
977 + %% remote_synchronous_timed_new_link( Node ) ->
978 +
979 + %% CreatorPid = self(),
980 +
981 + %% SpawnedPid = spawn_link( Node, fun() ->
982 + %% wooper_construct_and_run_synchronous(
983 + %% _ConstructParams=[], CreatorPid )
984 + %% end ),
985 +
986 + %% % Blocks until the spawned process answers or a time-out occurs:
987 + %% %
988 + %% % (no risk of synchronous spawns mismatch, as each synchronous call is
989 + %% % waited for)
990 + %% %
991 + %% receive
992 +
993 + %% { spawn_successful, SpawnedPid } ->
994 + %% SpawnedPid
995 +
996 + %% after ?synchronous_time_out ->
997 +
998 + %% throw( { remote_synchronous_linked_time_out, Node, ?MODULE } )
999 +
1000 + %% end.
1001 +
1002 +
1003 +
1004 + -endif. % use_synchronous_timed_new
1005 +
1006 + -endif. % use_remote_new
1007 +
1008 +
1009 + -endif. % -ifdef(wooper_construct_parameters).
1010 +
1011 +
1012 +
1013 +
1014 +
1015 + % Extensive testings in this mode.
1016 +
1017 + % Indirection level to allow constructors to be chained.
1018 + %
1019 + % Allows to obtain the virtual table from the instance, not from its parent.
1020 + %
1021 + %% -spec wooper_construct_and_run( construction_parameters() ) -> no_return().
1022 + %% wooper_construct_and_run( ConstructionParameters ) ->
1023 +
1024 + %% %trace_utils:debug_fmt("wooper_construct_and_run called with parameters ~w,"
1025 + %% % " whose length is ~B.~n",
1026 + %% % [ ConstructionParameters, length( ConstructionParameters ) ] ),
1027 +
1028 + %% wooper:construct_and_run( _Classname=?MODULE, ConstructionParameters ).
1029 +
1030 +
1031 +
1032 + % Indirection level to allow constructors to be chained.
1033 + %
1034 + % Allows to obtain the virtual table from the instance, not from its parent.
1035 + %
1036 + %% -spec wooper_construct_and_run_synchronous( construction_parameters(),
1037 + %% pid() ) -> no_return().
1038 + %% wooper_construct_and_run_synchronous( ConstructionParameters, SpawnerPid ) ->
1039 +
1040 + %% %trace_utils:debug_fmt("wooper_construct_and_run called with parameters ~w,"
1041 + %% % " whose length is ~B.~n",
1042 + %% % [ ConstructionParameters, length( ConstructionParameters ) ] ),
1043 +
1044 + %% wooper:construct_and_run_synchronous( _Classname=?MODULE,
1045 + %% ConstructionParameters, SpawnerPid ).
Loading more files…