Skip to content

Instantly share code, notes, and snippets.

@scartill
Created March 2, 2012 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scartill/1958293 to your computer and use it in GitHub Desktop.
Save scartill/1958293 to your computer and use it in GitHub Desktop.
Very easy Erlang gen_server helper (GPROC enabled)
% Extends gen_server behaviour to support GProc
-module(easy_gen_server).
-export([behaviour_info/1, spec/1, spec/2, on_init/1, on_init/2]).
% Behaviour definition
behaviour_info(callbacks) ->
gen_server:behaviour_info(callbacks)
++
[
{procname, 1}
];
behaviour_info(_Other) ->
undefined.
% Supervisor childspec
-spec spec(atom(), term()) -> supervisor:child_spec().
spec(Module, Arg) ->
ProcName = Module:procname(Arg),
{ProcName, {gen_server, start_link, [Module, Arg, []]}, permanent, 5000, worker, [Module]}.
-spec spec(atom()) -> supervisor:child_spec().
spec(Module) ->
spec(Module, none).
% Standard initialization helper
-spec on_init(atom()) -> term().
on_init(Module) ->
process_flag(trap_exit, true),
gproc:add_local_name(Module:procname(none)).
-spec on_init(atom(), term()) -> term().
on_init(Module, Arg) ->
process_flag(trap_exit, true),
gproc:add_local_name(Module:procname(Arg)).
% Fully standardized gen_server allowing autodispatch of the cast and calls
% Cast or call to it message like Handler or {Handler, Param}
% Handler is a private function of the module with prototypes:
%
% Handler(state()) -> stata()
% Handler(param(), state()) -> state()
%
% Macro GS_STD defines gen_server as one-liner
%
% Module which includes the file must have procname/1 as behaviour defines
% and procname/0 if GS_CAST is used without and process instance ID
%
% Note 1: calls are not supported at the moment
% Note 2: you can prepend any macro with your clause.
-behaviour(easy_gen_server).
-export([
init/1, handle_call/3, handle_cast/2, terminate/2,
handle_info/2, code_change/3,
procname/1]).
-define(GS_INIT,
init(Arg) ->
easy_gen_server:on_init(?MODULE),
State = initialize(Arg),
{ok, State}
).
-define(GS_STD_CAST,
handle_cast(stop, State) ->
{stop, normal, State};
handle_cast({Handler, Param}, State) ->
NewState = ?MODULE:Handler(Param, State),
{noreply, NewState};
handle_cast(Handler, State) ->
NewState = ?MODULE:Handler(State),
{noreply, NewState}
).
-define(GS_STD_CALL,
handle_call(get_state, _, State) ->
{reply, State, State}
).
-define(GS_NO_INFO,
handle_info(_, State) ->
{noreply, State}
).
-define(GS_STD_CODE_CHANGE,
code_change(_Vsn, State, _Extra) ->
{ok, State}
).
-define(GS_STD_TERMINATE,
terminate(_, _) ->
ok
).
-define(GS_CAST(Name),
Name() ->
gen_server:cast(procname(), Name)
).
-define(GS_CAST(Name, Param),
Name(Param) ->
gen_server:cast(procname(), {Name, Param})
).
-define(GS_CAST(Name, Param1, Param2),
Name(Param1, Param2) ->
gen_server:cast(procname(), {Name, {Param1, Param2}})
).
-define(GS_CAST(Name, Param1, Param2, Param3),
Name(Param1, Param2, Param3) ->
gen_server:cast(procname(), {Name, {Param1, Param2, Param3}})
).
-define(GS_CAST(Name, Param1, Param2, Param3, Param4),
Name(Param1, Param2, Param3, Param4) ->
gen_server:cast(procname(), {Name, {Param1, Param2, Param3, Param4}})
).
-define(GS_CASTI(Name),
Name(ID) ->
gen_server:cast(procname(ID), Name)
).
-define(GS_CASTI(Name, Param),
Name(ID, Param) ->
gen_server:cast(procname(ID), {Name, Param})
).
-define(GS_CASTI(Name, Param1, Param2),
Name(ID, Param1, Param2) ->
gen_server:cast(procname(ID), {Name, {Param1, Param2}})
).
-define(GS_CASTI(Name, Param1, Param2, Param3),
Name(ID, Param1, Param2, Param3) ->
gen_server:cast(procname(ID), {Name, {Param1, Param2, Param3}})
).
-define(GS_CASTI(Name, Param1, Param2, Param3, Param4),
Name(ID, Param1, Param2, Param3, Param4) ->
gen_server:cast(procname(ID), {Name, {Param1, Param2, Param3, Param4}})
).
% Navigation satellites data processing process
-module(sample).
-include("easy_gen_server.hrl").
-record(state, {
field
}).
% -= Interface
-export([test0/0, test1/1]).
-export([test0/1, test1/2]).
?GS_CAST(test0).
?GS_CAST(test1, Param).
% -= Genserver callbacks =-
% GProc and supervisor identifier
-spec procname(any()) -> navsats_dispatch.
procname(_) ->
my_genserver.
procname() ->
procname(none).
?GS_INIT.
?GS_STD_CAST.
?GS_STD_CALL.
?GS_NO_INFO.
?GS_STD_CODE_CHANGE.
?GS_STD_TERMINATE.
% -= Handlers
% Initialize the state
create_state(_) ->
#state{ }.
test0(State) ->
State.
test1(Param, State) ->
State.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment