我正在制作一个活动日历作为学校的任务,我是新手。 问题是当我在循环的接收部分延迟时,我的表消失了。 我现在正在网上和我的代码中查看错误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).
答案 0 :(得分:1)
问题可能是您的进程因start/0
函数崩溃而产生。当进程崩溃时,它拥有的任何ETS表都会被收集。尝试使用spawn_monitor
,然后使用shell的flush()命令来获取进来的消息。它可能会死掉。另一种方法是使用proc_lib
模块中的工具,然后使用erl -boot start_sasl
为您的流程报告并运行一些基本的崩溃错误。
“裸”spawn(...)
通常很危险,因为如果生成的进程崩溃,你将无法学到任何东西。至少使用spawn_link
或spawn_monitor
。
答案 1 :(得分:1)
我发现了我的问题:
我正在测试我的代码,但我没有要测试的Pid,所以我使用了whereis('event manager')
。相反,我必须使用self()
。