0

我正在制作一个活动日历作为学校的任务,我对此并不陌生。问题是,当我在循环的接收部分进行延迟时,我的表消失了。我在网上和我的代码中查找错误已有 2 天了。

事件是一个元组 => {{Time (tuple like now(), make_ref()}, NotifyPid, Load} getTime 通常返回一个整数

-module(calender).
-export([start/0, start_new/0, post/1, postincr/1, gettime/0]).
-export ([kalender/0, getTime/1, increment/1, makeTime/1]). % internal use only

%% @doc Starts the program
start() ->
    case whereis('event manager') =:= undefined of
        true ->
            register('event manager', spawn(calender, kalender, [])),
            {ok, 'event manager'};
        false ->
            {event_not_made}
    end.

%% @doc Starts a new program even program already exist but kills it first
start_new() ->
    case whereis('event manager') =:= undefined orelse unregister('event manager') of
        true ->
            ets:delete(calend),
            register('event manager', spawn(calender, kalender, [])),
            {ok, 'event manager'};
        false ->
            {ok, event_not_made}
    end.

% Puts Events into sorted table
% Time is an integer value in milliseconds  
post(Event) ->
    'event manager'!{post, Event},
    {ok, gettime()}.

%% @doc Puts Events into sorted table
%% Increment is an integer value which will be added to the present time
%% The increment value of time is in milliseconds
%% @end
postincr(Event) ->
    'event manager'!{postincr, Event},
    {ok, gettime()}.

%% @doc Gives the difference in time between present and time at start
gettime() ->
    'event manager'!{gettime, self()},
    receive
        T -> T
    end.

%% @private Calculates the difference of time between the present time and Event time
getTime(Time) ->
    NowTime = now(),
    timer:now_diff(Time, NowTime)div 1000.

%% @private Adds the incremental time of postincr to the present time
increment(Incr) ->
    {X, Y, Z} = now(),
    X1 = X * 1000000000000,
    Y1 = Y * 1000000,
    Incr1 = X1 + Y1 + Z + (Incr * 1000),
    makeTime(Incr1).

%% @private Changes integer to tuple of 3 values
makeTime(Time) ->
    X = Time div 1000000000000,
    Y = (Time rem 1000000000000) div 1000000,
    Z = Time rem 1000000,
    {X, Y, Z}.

%% @private Makes the sorted table, starts the loop
kalender() ->
    Cal = {ets:new(calend, [ordered_set, named_table, {keypos, 1}, public]), now()},
    loop(Cal).

%% @private Loops through the table and checks for received messages
loop(Cal) ->
    io:format("Loop start ~n"),
    {Calen, TimeAtStart} = Cal,

    io:format("Before case ~n"),
    case ets:first(Calen)  of
        '$end_of_table' ->
            io:format("end of table ~n"),
            {end_of_table};
        {Time, Ref} ->
            io:format("Before calculation event ~n"),
            Ms = getTime(Time),
            io:format("After getTime ~n"),
            if 
                Ms =< 0 ->
                    io:format("Ms =< 0 ~n"),
                    [Event | _Rest] = ets:lookup(Calen, {Time, Ref}),
                    io:format("~p~n", [Event]),
                    {{_Time1, _Ref1}, NotifyPid, _Load} = Event,
                    io:format("~p~n", [NotifyPid]),
                    NotifyPid!Event,
                    io:format("After event send ~n"),
                    ets:delete(Calen, {Time, Ref}),
                    io:format("After Ms =< 0 ~n");
                Ms > 0 ->
                    io:format("Event not done ~n"),
                    {event_not_yet_done}
            end,
            io:format("After calculation event ~n")
    end,

我认为它从这里的某个地方出错了:

io:format("Before Delay ~n"),
        % Gets the delay time
        Delay = case ets:first(Calen) of
            '$end_of_table' ->
                io:format("Delay infinity ~n"),
                infinity;
            {DelayTime, _DelayRef} ->
                io:format("~p~n", [DelayTime]), => the DelayTime has for example a value of {9283,823031,155000}

                Dl = getTime(DelayTime),
                case Dl > 0 of
                    true ->
                        Dl,
                        io:format("~p~n", [Dl]); => this io:format gives me on the screen a calculated value example: 7899995274337

                    false ->
                        0,
                        io:format("0 ~n")
                end,
                io:format("Delay time~n")
        end,

        io:format("Before receive ~n"),
        receive
            {post, PostEvent} -> 
                io:format("In post ~n"),
                {PostTimeI, Np, Ld} = PostEvent,
                PostRef = make_ref(),
                PostTimeT = makeTime((PostTimeI * 1000)),
                io:format("After making the tuples ~n"),
                io:format("~p   ~p  ~p  ~p  ~p~n", [PostTimeI, PostRef, PostTimeT, Np, Ld]),
                ets:insert(Calen, {{PostTimeT, PostRef}, Np, Ld}),
                io:format("After insert post ~p~n", [whereis('event manager')]);
            {postincr, PostIncrEvent} ->
                {Incr, Np, Ld} = PostIncrEvent,
                PostIncrRef = make_ref(),
                PostIncrTime = increment(Incr),
                ets:insert(Calen, {{PostIncrTime, PostIncrRef}, Np, Ld});
            {gettime, From} ->
                From!getTime(TimeAtStart)
            after
                Delay ->
                    io:format("Delaying ~n"),
                    {ok}
        end,
        io:format("After receive ~n"),
        loop(Cal).
4

2 回答 2

1

问题可能是您的进程随着您的start/0函数崩溃而产生。当一个进程崩溃时,它拥有的所有 ETS 表都会被回收。尝试使用spawn_monitor然后使用 shell 的 flush() 命令来获取传入的消息。它可能会死掉。另一种方法是使用proc_lib模块中的工具,然后使用erl -boot start_sasl为您的进程启动和运行一些基本的崩溃错误报告。

“裸”spawn(...)通常是危险的,因为如果生成的进程崩溃,您将一无所获。至少使用spawn_linkor spawn_monitor

于 2013-11-07T17:57:57.583 回答
1

我发现了我的问题:我正在测试我的代码,但我没有要测试的 Pid,所以我使用了whereis('event manager'). 相反,我不得不使用self().

于 2013-11-08T19:28:59.837 回答