Skip to content

Commit cfc21d0

Browse files
author
José Valim
committed
Merge pull request #958 from yrashk/gen-event-behaviour
Implement GenEvent.Behaviour
2 parents e3c6cc9 + 507fda5 commit cfc21d0

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed

lib/elixir/lib/gen_event/behaviour.ex

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
defmodule GenEvent.Behaviour do
2+
@moduledoc """
3+
This module is a convenience to define GenEvent callbacks in Elixir.
4+
5+
GenEvent is an OTP behaviour that encapsulates event handling functionality.
6+
7+
## Example
8+
9+
Bellow follows an example of a GenEvent that stores notifications
10+
until they are fetched:
11+
12+
defmodule MyEventHandler do
13+
use GenEvent.Behaviour
14+
15+
# Callbacks
16+
17+
def init(_) do
18+
{ :ok, [] }
19+
end
20+
21+
def handle_event({:notification, x}, notifications) do
22+
{ :ok, [x|notifications] }
23+
end
24+
25+
def handle_call(:notifications, notifications) do
26+
{:ok, Enum.reverse(notifications), []}
27+
end
28+
29+
end
30+
31+
{ :ok, pid } = :gen_event.start_link
32+
33+
:gen_event.add_handler(pid, MyEventHandler, [])
34+
35+
:gen_event.notify(pid, {:notification, 1})
36+
:gen_event.notify(pid, {:notification, 2})
37+
38+
:gen_event.call(pid, MyEventHandler, :notifications)
39+
#=> [1, 2]
40+
41+
:gen_event.call(pid, MyEventHandler, :notifications)
42+
#=> []
43+
44+
Notice we never call the server callbacks directly, they are called
45+
by OTP whenever we interact with the server.
46+
47+
Starting and sending messages to gen_event is done
48+
via Erlang's `:gen_event` module. For more information,
49+
please refer to the following:
50+
51+
http://www.erlang.org/doc/man/gen_event.html
52+
http://learnyousomeerlang.com/event-handlers
53+
"""
54+
55+
@doc false
56+
defmacro __using__(_) do
57+
quote location: :keep do
58+
@behavior :gen_event
59+
60+
def init(args) do
61+
{ :ok, args }
62+
end
63+
64+
def handle_event(_event, state) do
65+
{ :ok, state }
66+
end
67+
68+
def handle_call(_request, state) do
69+
{ :ok, :ok, state }
70+
end
71+
72+
def handle_info(_msg, state) do
73+
{ :ok, state }
74+
end
75+
76+
def terminate(reason, state) do
77+
:ok
78+
end
79+
80+
def code_change(_old, state, _extra) do
81+
{ :ok, state }
82+
end
83+
84+
defoverridable [init: 1,
85+
handle_event: 2,
86+
handle_call: 2, handle_info: 2,
87+
terminate: 2, code_change: 3]
88+
end
89+
end
90+
end
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Code.require_file "../../test_helper.exs", __FILE__
2+
3+
defmodule GenEvent.BehaviourTest do
4+
use ExUnit.Case, async: true
5+
6+
defmodule MyEventHandler do
7+
use GenEvent.Behaviour
8+
9+
# Callbacks
10+
11+
def init(_) do
12+
{ :ok, [] }
13+
end
14+
15+
def handle_event({:notification, x}, notifications) do
16+
{ :ok, [x|notifications] }
17+
end
18+
19+
def handle_call(:notifications, notifications) do
20+
{:ok, Enum.reverse(notifications), []}
21+
end
22+
23+
end
24+
25+
test :using do
26+
{ :ok, pid } = :gen_event.start_link
27+
:gen_event.add_handler(pid, MyEventHandler, [])
28+
29+
:gen_event.notify(pid, {:notification, 1})
30+
:gen_event.notify(pid, {:notification, 2})
31+
32+
assert :gen_event.call(pid, MyEventHandler, :notifications) == [1,2]
33+
assert :gen_event.call(pid, MyEventHandler, :notifications) == []
34+
end
35+
36+
end

0 commit comments

Comments
 (0)