43
43
-export ([
44
44
start /3 , start /4 ,
45
45
start_link /3 , start_link /4 ,
46
+ start_monitor /3 , start_monitor /4 ,
46
47
stop /1 , stop /3 ,
47
48
call /2 , call /3 ,
48
49
cast /2 ,
109
110
110
111
% % @private
111
112
do_spawn (Module , Args , Options , SpawnOpts ) ->
112
- Pid = spawn_opt (? MODULE , init_it , [self (), Module , Args , Options ], SpawnOpts ),
113
- case wait_ack (Pid ) of
114
- ok -> {ok , Pid };
113
+ PidOrMonRet = spawn_opt (? MODULE , init_it , [self (), Module , Args , Options ], SpawnOpts ),
114
+ case wait_ack (PidOrMonRet ) of
115
+ ok -> {ok , PidOrMonRet };
115
116
{error , Reason } -> {error , Reason }
116
117
end .
117
118
@@ -123,6 +124,15 @@ do_spawn(Name, Module, Args, Options, SpawnOpts) ->
123
124
{error , Reason } -> {error , Reason }
124
125
end .
125
126
127
+ % % @private
128
+ spawn_if_not_registered (Name , Module , Args , Options , SpawnOpts ) ->
129
+ case erlang :whereis (Name ) of
130
+ undefined ->
131
+ do_spawn (Name , Module , Args , [{name , Name } | Options ], SpawnOpts );
132
+ Pid ->
133
+ {error , {already_started , Pid }}
134
+ end .
135
+
126
136
init_it (Starter , Name , Module , Args , Options ) ->
127
137
try erlang :register (Name , self ()) of
128
138
true ->
@@ -209,7 +219,11 @@ init_ack(Parent, Return) ->
209
219
Parent ! {ack , self (), Return },
210
220
ok .
211
221
212
- wait_ack (Pid ) ->
222
+ wait_ack (Pid ) when is_pid (Pid ) ->
223
+ receive
224
+ {ack , Pid , Return } -> Return
225
+ end ;
226
+ wait_ack ({Pid , _MonRef }) when is_pid (Pid ) ->
213
227
receive
214
228
{ack , Pid , Return } -> Return
215
229
end .
@@ -246,12 +260,7 @@ crash_report(ErrStr, Parent, E, S) ->
246
260
Options :: options ()
247
261
) -> {ok , pid ()} | {error , Reason :: term ()}.
248
262
start ({local , Name }, Module , Args , Options ) when is_atom (Name ) ->
249
- case erlang :whereis (Name ) of
250
- undefined ->
251
- do_spawn (Name , Module , Args , [{name , Name } | Options ], []);
252
- Pid ->
253
- {error , {already_started , Pid }}
254
- end .
263
+ spawn_if_not_registered (Name , Module , Args , Options , []).
255
264
256
265
% %-----------------------------------------------------------------------------
257
266
% % @param Module the module in which the gen_server callbacks are defined
@@ -292,12 +301,7 @@ start(Module, Args, Options) ->
292
301
Options :: options ()
293
302
) -> {ok , pid ()} | {error , Reason :: term ()}.
294
303
start_link ({local , Name }, Module , Args , Options ) when is_atom (Name ) ->
295
- case erlang :whereis (Name ) of
296
- undefined ->
297
- do_spawn (Name , Module , Args , [{name , Name } | Options ], [link ]);
298
- Pid ->
299
- {error , {already_started , Pid }}
300
- end .
304
+ spawn_if_not_registered (Name , Module , Args , Options , [link ]).
301
305
302
306
% %-----------------------------------------------------------------------------
303
307
% % @param Module the module in which the gen_server callbacks are defined
@@ -316,6 +320,49 @@ start_link({local, Name}, Module, Args, Options) when is_atom(Name) ->
316
320
start_link (Module , Args , Options ) ->
317
321
do_spawn (Module , Args , Options , [link ]).
318
322
323
+ % %-----------------------------------------------------------------------------
324
+ % % @param Module the module in which the gen_server callbacks are defined
325
+ % % @param Args the arguments to pass to the module's init callback
326
+ % % @param Options the options used to create the gen_server
327
+ % % @returns the gen_server pid and monitor reference tuple if successful;
328
+ % % {error, Reason}, otherwise.
329
+ % % @doc Start and monitor an un-named gen_server.
330
+ % %
331
+ % % This function will start a gen_server instance.
332
+ % %
333
+ % % <em><b>Note.</b> The Options argument is currently ignored.</em>
334
+ % % @end
335
+ % %-----------------------------------------------------------------------------
336
+ -spec start_monitor (Module :: module (), Args :: term (), Options :: options ()) ->
337
+ {ok , {Pid :: pid (), MonRef :: reference ()}} | {error , Reason :: term ()}.
338
+ start_monitor (Module , Args , Options ) ->
339
+ do_spawn (Module , Args , Options , [monitor ]).
340
+
341
+ % %-----------------------------------------------------------------------------
342
+ % % @param ServerName the name with which to register the gen_server
343
+ % % @param Module the module in which the gen_server callbacks are defined
344
+ % % @param Args the arguments to pass to the module's init callback
345
+ % % @param Options the options used to create the gen_server
346
+ % % @returns the gen_server pid and monitor reference tuple if successful;
347
+ % % {error, Reason}, otherwise.
348
+ % % @doc Start and monitor a named gen_server.
349
+ % %
350
+ % % This function will start a gen_server instance and register the
351
+ % % newly created process with the process registry. Subsequent calls
352
+ % % may use the gen_server name, in lieu of the process id.
353
+ % %
354
+ % % <em><b>Note.</b> The Options argument is currently ignored.</em>
355
+ % % @end
356
+ % %-----------------------------------------------------------------------------
357
+ -spec start_monitor (
358
+ ServerName :: {local , Name :: atom ()},
359
+ Module :: module (),
360
+ Args :: term (),
361
+ Options :: options ()
362
+ ) -> {ok , {Pid :: pid (), MonRef :: reference ()}} | {error , Reason :: term ()}.
363
+ start_monitor ({local , Name }, Module , Args , Options ) when is_atom (Name ) ->
364
+ spawn_if_not_registered (Name , Module , Args , Options , [monitor ]).
365
+
319
366
% %-----------------------------------------------------------------------------
320
367
% % @equiv stop(ServerRef, normal, infinity)
321
368
% % @doc Stop a previously started gen_server instance.
0 commit comments