erlang之实现简单的提醒记事本

文件evserv2.erl

-module(evserv2).
-compile(export_all).
-record(state,{events,clients}).
-record(event,{name="",description="",pid,timeout}).
init() ->
	loop(#state{events = orddict:new(), clients = orddict:new()}).%初始化,维护2个列表,事件列表和客户端列表


send_to_clients(Msg, ClientDict) ->%发送消息
	orddict:map(fun(_Ref, Pid) ->Pid ! Msg end, ClientDict).%根据客户端标签,把消息发送给客户端

loop(S = #state{}) ->%服务器抽象
	receive
		{Pid, MsgRef, {subscribe, Client}} ->%订阅通知
			Ref = erlang:monitor(process, Client),%添加一个监视器
			NewClient = orddict:store(Ref,Client,S#state.clients),%把新的客户端添加进客户端列表,记录有事件标签和客户端的标签
			Pid ! {MsgRef, ok},%发送确定消息
			loop(S#state{clients=NewClient});

		{Pid, MsgRef, {add, Name,Description,Timeout}} ->%添加事件通知,Name是唯一的事件标记
				EventPid = event:start_link(Name,Timeout),%创建事件进程
				NewEvents = orddict:store(Name,%新增一个
						#event{
							name = Name,%唯一标记
							description =Description,%描述
							pid = EventPid,%事件进程PID
							timeout = Timeout%多少秒后发
						},
					S#state.events),
				Pid ! {MsgRef, ok},
				loop(S#state{events = NewEvents});

		{Pid, MsgRef, {cancel, Name}} ->%删除事件
			Events = case  orddict:find(Name,S#state.events) of%根据唯一标签找到事件
				{ok, E} ->
					events:cancel(E#event.pid),%删除事件进程
					orddict:erase(Name, S#state.events);%删除列表中的事件
				error ->
					S#state.events
			end,
			Pid ! {MsgRef, ok},
			loop(S#state{events=Events});

		{done, Name} ->%事件发送事件
			case orddict:find(Name, S#state.events) of%先把他找出来是谁做完了
				{ok, E} ->
					send_to_clients({done, E#event.name,E#event.description},
						S#state.clients),%发送消息
					NewEvents = orddict:erase(Name, S#state.events),%删除掉 根据唯一ID
					loop(S#state{events=NewEvents});
				error ->
					loop(s)
			end;

		shutdown ->
			exit(shutdown);

		{'DOWN', Ref, process, _Pid, _Reason} ->
			loop(S#state{clients=orddict:erase(Ref, S#state.clients)});

		code_change ->
			?MODULE:loop(S);
		Unknow ->
			io:format("Unknown message: ~p~n",[Unknow]),
			loop(S)
	end.

start() ->
	register(?MODULE, Pid=spawn(?MODULE, init, [])),%注册一个进程,而且唯一,不能重复定义
	Pid.

start_link() ->
	register(?MODULE, Pid = spawn(?MODULE,init,[])),
	Pid.

terminate() ->
	?MODULE ! shutdown.

subscribe(Pid) ->%订阅抽象
	Ref = erlang:monitor(process, whereis(?MODULE)),
	?MODULE ! {self(), Ref, {subscribe, Pid}},%因为服务器唯一 而且使用MODULE标记的 所以可以这样写
	receive
		{Ref, ok} ->
			{ok, Ref};
		{'DOWN', Ref, process, _Pid, Reason} ->
			{error,Reason}
		after 5000 ->
			{error, timeout}
	end.

add_event(Name, Description, Timeout) ->%添加事件抽象
	Ref = make_ref(),
	?MODULE ! {self(), Ref, {add, Name,Description,Timeout}},
	receive
		{Ref, Msg} ->
			Msg
		after 5000 ->
			{error, timeout}
	end.

add_event2(Name, Description, Timeout) ->
	Ref = make_ref(),
	?MODULE ! {self(), Ref, {add, Name,Description,Timeout}},
	receive
		{Ref, {error, Reason}} -> erlang:error(Reason);
		{Ref, Msg} -> Msg 
		after 5000 ->
			{error, timeout}
	end.

cancel(Name) ->
	Ref = make_ref(),
	?MODULE ! {self(), Ref, {cancel, Name}},
	receive
		{Ref, ok} -> ok
	after 5000 ->
			{error, timeout}
	end.

listen(Deply) ->
	receive
			M = {done, _Name, _Descrption} ->
				[M|listen(0)]
	after Deply*1000 ->
		[]
	end.

 

 文件event.erl

-module(event).
-export([loop/1,start/2,init/3,cancel/1,start_link/2]).
-record(state,{server,name="",to_go=0}).%server发给谁,name信息,go秒数

loop(S = #state{server=Server}) ->
	receive
		{Server,Ref,cancel} ->
			Server ! {Ref, ok}
	after S#state.to_go*1000 ->
		Server ! {done,S#state.name}
	end.
	
start(Event,Dplay) ->
	spawn(?MODULE, init, [self(), Event, Dplay]).


start_link(Event,Dplay) ->
	spawn_link(?MODULE, init, [self(), Event, Dplay]).

init(Server,Event,Dplay) ->
	loop(#state{server = Server,name = Event, to_go = Dplay}).

cancel(Pid) ->
	Ref = erlang:monitor(process, Pid),
	Pid ! {self(), Ref, cancel},
	receive
		{Ref, ok} ->
			erlang:demonitor(Ref, [flush]),
			ok;
		{'DOWN',Ref,process,Pid,_Reason} ->
			ok
	end.
	

1.学习到了orrdict的使用,这是erl自带的一个字典,而且key是唯一的,因为这是一个个人用的,所以够用了.

2.学到了一些封装抽象的思想

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值