329
332
%%% ---------------------------------------------------
330
333
init_it(Starter, self, Name, Mod, Args, Options) ->
331
334
init_it(Starter, self(), Name, Mod, Args, Options);
332
init_it(Starter, Parent, Name, Mod, Args, Options) ->
335
init_it(Starter, Parent, Name0, Mod, Args, Options) ->
333
337
Debug = gen:debug_options(Options),
334
Limits= limit_options(Options),
338
Limits = limit_options(Options),
335
341
case catch Mod:init(Args) of
336
342
{ok, StateName, StateData} ->
337
343
proc_lib:init_ack(Starter, {ok, self()}),
338
loop(Parent, Name, StateName, StateData, Mod, infinity, Debug, Limits);
344
loop(Parent, Name, StateName, StateData, Mod, infinity, Debug, Limits, Queue, QueueLen);
339
345
{ok, StateName, StateData, Timeout} ->
340
346
proc_lib:init_ack(Starter, {ok, self()}),
341
loop(Parent, Name, StateName, StateData, Mod, Timeout, Debug, Limits);
347
loop(Parent, Name, StateName, StateData, Mod, Timeout, Debug, Limits, Queue, QueueLen);
342
348
{stop, Reason} ->
343
349
proc_lib:init_ack(Starter, {error, Reason}),
363
name({local,Name}) -> Name;
364
name({global,Name}) -> Name;
365
name(Pid) when is_pid(Pid) -> Pid.
357
367
%%-----------------------------------------------------------------
359
369
%%-----------------------------------------------------------------
370
loop(Parent, Name, StateName, StateData, Mod, hibernate, Debug,
371
Limits, Queue, QueueLen)
373
case queue:out(Queue) of
374
{{value, Msg}, Queue1} ->
375
decode_msg(Msg, Parent, Name, StateName, StateData, Mod, hibernate,
376
Debug, Limits, Queue1, QueueLen - 1, false);
378
Reason = internal_queue_error,
379
error_info(Reason, Name, hibernate, StateName, StateData, Debug),
382
loop(Parent, Name, StateName, StateData, Mod, hibernate, Debug,
383
Limits, _Queue, _QueueLen) ->
384
proc_lib:hibernate(?MODULE,wake_hib,
385
[Parent, Name, StateName, StateData, Mod,
360
387
%% First we test if we have reach a defined limit ...
361
loop(Parent, Name, StateName, StateData, Mod, Time, Debug, Limits) ->
388
loop(Parent, Name, StateName, StateData, Mod, Time, Debug,
389
Limits, Queue, QueueLen) ->
363
message_queue_len(Limits)
391
message_queue_len(Limits, QueueLen)
364
392
%% TODO: We can add more limit checking here...
366
394
{process_limit, Limit} ->
369
397
terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug)
371
399
process_message(Parent, Name, StateName, StateData,
372
Mod, Time, Debug, Limits).
400
Mod, Time, Debug, Limits, Queue, QueueLen).
373
401
%% ... then we can process a new message:
374
process_message(Parent, Name, StateName, StateData, Mod, Time, Debug, Limits) ->
402
process_message(Parent, Name, StateName, StateData, Mod, Time, Debug,
403
Limits, Queue, QueueLen) ->
404
{Msg, Queue1, QueueLen1} = collect_messages(Queue, QueueLen, Time),
405
decode_msg(Msg,Parent, Name, StateName, StateData, Mod, Time,
406
Debug, Limits, Queue1, QueueLen1, false).
408
collect_messages(Queue, QueueLen, Time) ->
412
{'EXIT', _Parent, priority_shutdown} ->
413
{Input, Queue, QueueLen};
416
queue:in(Input, Queue), QueueLen + 1, Time)
419
case queue:out(Queue) of
420
{{value, Msg}, Queue1} ->
421
{Msg, Queue1, QueueLen - 1};
425
{Input, Queue, QueueLen}
427
{{'$gen_event', timeout}, Queue, QueueLen}
433
wake_hib(Parent, Name, StateName, StateData, Mod, Debug,
376
{'EXIT', Parent, priority_shutdown} ->
377
{'EXIT', Parent, priority_shutdown}
383
{'$gen_event', timeout}
441
decode_msg(Msg, Parent, Name, StateName, StateData, Mod, hibernate,
442
Debug, Limits, Queue, QueueLen, true).
444
decode_msg(Msg,Parent, Name, StateName, StateData, Mod, Time, Debug,
445
Limits, Queue, QueueLen, Hib) ->
446
put('$internal_queue_len', QueueLen),
387
448
{system, From, Req} ->
388
449
sys:handle_system_msg(Req, From, Parent, ?MODULE, Debug,
389
450
[Name, StateName, StateData,
451
Mod, Time, Limits, Queue, QueueLen], Hib);
391
452
{'EXIT', Parent, Reason} ->
392
453
terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug);
393
454
_Msg when Debug == [] ->
394
455
handle_msg(Msg, Parent, Name, StateName, StateData,
456
Mod, Time, Limits, Queue, QueueLen);
397
458
Debug1 = sys:handle_debug(Debug, {?MODULE, print_event},
398
459
{Name, StateName}, {in, Msg}),
399
460
handle_msg(Msg, Parent, Name, StateName, StateData,
400
Mod, Time, Debug1, Limits)
461
Mod, Time, Debug1, Limits, Queue, QueueLen)
403
464
%%-----------------------------------------------------------------
404
465
%% Callback functions for system messages handling.
405
466
%%-----------------------------------------------------------------
407
467
system_continue(Parent, Debug, [Name, StateName, StateData,
408
Mod, Time, Limits]) ->
409
loop(Parent, Name, StateName, StateData, Mod, Time, Debug, Limits).
468
Mod, Time, Limits, Queue, QueueLen]) ->
469
loop(Parent, Name, StateName, StateData, Mod, Time, Debug,
470
Limits, Queue, QueueLen).
411
472
system_terminate(Reason, _Parent, Debug,
412
473
[Name, StateName, StateData, Mod, _Time, _Limits]) ->
413
474
terminate(Reason, Name, [], Mod, StateName, StateData, Debug).
415
system_code_change([Name, StateName, StateData, Mod, Time, Limits],
476
system_code_change([Name, StateName, StateData, Mod, Time,
477
Limits, Queue, QueueLen],
416
478
_Module, OldVsn, Extra) ->
417
479
case catch Mod:code_change(OldVsn, StateName, StateData, Extra) of
418
480
{ok, NewStateName, NewStateData} ->
419
{ok, [Name, NewStateName, NewStateData, Mod, Time, Limits]};
481
{ok, [Name, NewStateName, NewStateData, Mod, Time,
482
Limits, Queue, QueueLen]};
453
516
io:format(Dev, "*DBG* ~p switched to state ~w~n",
454
517
[Name, StateName]).
456
handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time, Limits) -> %No debug here
519
handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time,
520
Limits, Queue, QueueLen) -> %No debug here
457
521
From = from(Msg),
458
522
case catch dispatch(Msg, Mod, StateName, StateData) of
459
523
{next_state, NStateName, NStateData} ->
460
524
loop(Parent, Name, NStateName, NStateData,
461
Mod, infinity, [], Limits);
525
Mod, infinity, [], Limits, Queue, QueueLen);
462
526
{next_state, NStateName, NStateData, Time1} ->
463
loop(Parent, Name, NStateName, NStateData, Mod, Time1, [], Limits);
464
{reply, Reply, NStateName, NStateData} when From /= undefined ->
527
loop(Parent, Name, NStateName, NStateData, Mod, Time1, [],
528
Limits, Queue, QueueLen);
529
{reply, Reply, NStateName, NStateData} when From =/= undefined ->
465
530
reply(From, Reply),
466
531
loop(Parent, Name, NStateName, NStateData,
467
Mod, infinity, [], Limits);
468
{reply, Reply, NStateName, NStateData, Time1} when From /= undefined ->
532
Mod, infinity, [], Limits, Queue, QueueLen);
533
{reply, Reply, NStateName, NStateData, Time1} when From =/= undefined ->
469
534
reply(From, Reply),
470
loop(Parent, Name, NStateName, NStateData, Mod, Time1, [], Limits);
535
loop(Parent, Name, NStateName, NStateData, Mod, Time1, [],
536
Limits, Queue, QueueLen);
471
537
{stop, Reason, NStateData} ->
472
538
terminate(Reason, Name, Msg, Mod, StateName, NStateData, []);
473
{stop, Reason, Reply, NStateData} when From /= undefined ->
539
{stop, Reason, Reply, NStateData} when From =/= undefined ->
474
540
{'EXIT', R} = (catch terminate(Reason, Name, Msg, Mod,
475
541
StateName, NStateData, [])),
476
542
reply(From, Reply),
485
551
handle_msg(Msg, Parent, Name, StateName, StateData,
486
Mod, _Time, Debug, Limits) ->
552
Mod, _Time, Debug, Limits, Queue, QueueLen) ->
487
553
From = from(Msg),
488
554
case catch dispatch(Msg, Mod, StateName, StateData) of
489
555
{next_state, NStateName, NStateData} ->
490
556
Debug1 = sys:handle_debug(Debug, {?MODULE, print_event},
491
557
{Name, NStateName}, return),
492
558
loop(Parent, Name, NStateName, NStateData,
493
Mod, infinity, Debug1, Limits);
559
Mod, infinity, Debug1, Limits, Queue, QueueLen);
494
560
{next_state, NStateName, NStateData, Time1} ->
495
561
Debug1 = sys:handle_debug(Debug, {?MODULE, print_event},
496
562
{Name, NStateName}, return),
497
563
loop(Parent, Name, NStateName, NStateData,
498
Mod, Time1, Debug1, Limits);
499
{reply, Reply, NStateName, NStateData} when From /= undefined ->
500
Debug1 = reply(Name, From, Reply, Debug, NStateName),
501
loop(Parent, Name, NStateName, NStateData,
502
Mod, infinity, Debug1, Limits);
503
{reply, Reply, NStateName, NStateData, Time1} when From /= undefined ->
504
Debug1 = reply(Name, From, Reply, Debug, NStateName),
505
loop(Parent, Name, NStateName, NStateData,
506
Mod, Time1, Debug1, Limits);
564
Mod, Time1, Debug1, Limits, Queue, QueueLen);
565
{reply, Reply, NStateName, NStateData} when From =/= undefined ->
566
Debug1 = reply(Name, From, Reply, Debug, NStateName),
567
loop(Parent, Name, NStateName, NStateData,
568
Mod, infinity, Debug1, Limits, Queue, QueueLen);
569
{reply, Reply, NStateName, NStateData, Time1} when From =/= undefined ->
570
Debug1 = reply(Name, From, Reply, Debug, NStateName),
571
loop(Parent, Name, NStateName, NStateData,
572
Mod, Time1, Debug1, Limits, Queue, QueueLen);
507
573
{stop, Reason, NStateData} ->
508
574
terminate(Reason, Name, Msg, Mod, StateName, NStateData, Debug);
509
{stop, Reason, Reply, NStateData} when From /= undefined ->
575
{stop, Reason, Reply, NStateData} when From =/= undefined ->
510
576
{'EXIT', R} = (catch terminate(Reason, Name, Msg, Mod,
511
577
StateName, NStateData, Debug)),
512
578
reply(Name, From, Reply, Debug, StateName),