Skip to content

Instantly share code, notes, and snippets.

@garrensmith
Created January 29, 2012 07:43
Show Gist options
  • Select an option

  • Save garrensmith/1697736 to your computer and use it in GitHub Desktop.

Select an option

Save garrensmith/1697736 to your computer and use it in GitHub Desktop.
Fridge Process implementation
-module(kitchen2).
-compile(export_all).
start(Items) ->
spawn_link(?MODULE, restarter, [Items]),
timer:sleep(100). %delay for processes to startup befor can issue commands
% register(fridge, Pid).
restarter(Items) ->
process_flag(trap_exit, true),
Pid = spawn_link(?MODULE, fridge, [Items]),
register(fridge, Pid),
cool_spawner(),
receive
{'EXIT', Pid, normal} -> % not a crash
ok;
{'EXIT', Pid, shutdown} -> % manual termination, not a crash
ok;
{'EXIT', Pid, _} ->
restarter([])
end.
command(Msg) ->
Ref = make_ref(),
fridge ! {self(), Ref,Msg},
receive
{_, Ref, Resp} -> Resp
after 20 ->
timeout
end.
store(Item) ->
command({store, Item}).
take(Item) ->
command({take, Item}).
list_items() ->
command(list).
turn_off() ->
command(kill).
take_from_fridge(Item, Foodlist) ->
case lists:keymember(Item,1, Foodlist) of
true ->
ItemWithTemp = lists:keyfind(Item,1, Foodlist),
{{ok, ItemWithTemp }, lists:keydelete(Item,1, Foodlist)};
false ->
{{fail, "Item does not exist"}, Foodlist}
end.
fridge(Foodlist1) ->
Foodlist = lists:sort(Foodlist1), % sort every time to make merging easy
receive
{_, _, unplug} ->
start_temp_monitor(),
fridge(Foodlist);
{_,_, plug} ->
stop_temp_monitor(),
fridge(Foodlist);
{From, Ref, kill} ->
cooler ! {self(), make_ref(), kill},
From ! {self(), Ref, ok};
{From, Ref, list} ->
From ! {self(), Ref, Foodlist},
fridge(Foodlist);
{From, Ref, {store, Item}} ->
From ! {self(), Ref, ok},
fridge([Item | Foodlist]);
{From, Ref, {take, Item}} ->
{Resp, NewFoodList} = take_from_fridge(Item, Foodlist),
From ! {self(), Ref, Resp},
fridge(NewFoodList);
{_, _, {cold, ColdFoodList}} ->
NewFoodList = lists:ukeymerge(1,ColdFoodList, Foodlist),
fridge(NewFoodList)
end.
temp_monitor(Temp) ->
receive
{_, _, kill} -> ok
after 1000 ->
if Temp > 15 ->
io:format("WARNING: Temperature above 15 degrees~n"),
temp_monitor(Temp + 1);
true -> temp_monitor(Temp + 1)
end
end.
start_temp_monitor() ->
Pid = spawn_link(?MODULE, temp_monitor, [17]),
register(temp_monitor, Pid),
ok.
stop_temp_monitor() ->
temp_monitor ! {self(), make_ref(), kill}.
cool_item(FoodItem) ->
case FoodItem of
{Item, Temp} when Temp > 10 -> {Item, Temp - 1};
{Item, Temp} when Temp =< 10 -> {Item, Temp}
end.
cool_spawner() ->
Pid = spawn_link(?MODULE, cooler, []),
register(cooler, Pid).
cooler() ->
receive
{_, _, kill} -> ok
after 300 ->
Foodlist = command(list),
ColdFoodList = lists:map(fun cool_item/1, Foodlist),
command({cold, ColdFoodList}),
cooler()
end.
test() ->
test_take_from_fridge(),
test_cool(),
test_fridge(),
test_unplug(),
ok.
test_unplug() ->
start([{cheese,12}, {bread,8}]),
command(unplug),
timer:sleep(5000),
command(plug),
turn_off().
test_fridge() ->
start([{cheese,12}, {bread,8}]),
[{bread,8}, {cheese,12} ] = list_items(),
ok = store({milk, 15}),
[{bread,8}, {cheese,12}, {milk,15}] = list_items(),
ok = store({crab,5}),
{ok, {milk, 15}} = take(milk),
[{bread,8}, {cheese,12}, {crab,5}] = list_items(),
{fail, "Item does not exist"} = take(ham),
ok = turn_off(),
ok.
test_cool() ->
start([{cheese,9},{milk, 8},{bread,12}]),
timer:sleep(400),
[{bread,11},{cheese,9},{milk,8}] = list_items(),
store({honey, 15}),
timer:sleep(300),
[{bread,10},{cheese,9},{honey,14},{milk,8}] = list_items(),
ok = turn_off(),
timer:sleep(200),
ok.
test_take_from_fridge() ->
{{ok,{cheese,12}},[{bread,8},{crab,5}]} = take_from_fridge(cheese, [{bread,8}, {cheese,12}, {crab,5}]),
{{fail,"Item does not exist"}, [{bread,8},{cheese,12},{crab,5}]} = take_from_fridge(mango, [{bread,8}, {cheese,12}, {crab,5}]),
ok.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment