Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions lib/exactor/common.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
defmodule ExActor.Common do
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're introducing this module, then moving the code of ExActor.Helper.init_generation_state to the __using__ might be nice. That way, we get to keep the common boilerplate in the same place.

@moduledoc false

# This module adds common functionality to all ExActor behaviours.
defmacro __using__(_opts) do
quote do
@doc """
By default, the `server` argument given
to the different interface functions, is expected to be a process identifier,
unless overridden by the `export:` option.

But by providing a custom implementation of `server_pid/1`, you can map an identifier
to a PID by some other means.
"""
def server_pid(server_reference) do
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should make this public. By doing it, we're by default adding extra function to the module's interface, and I'm not sure I like that. Preferably, this would be a defp, though I'm not sure if defoverridable would work then. If it doesn't, then we could make it @doc false so it's not included in the generated docs, and marked as an internal detail.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think we shouldn't inject this function for the cases where a global :export option is provided.

server_reference
end

defoverridable [server_pid: 1]
end
end
end
1 change: 1 addition & 0 deletions lib/exactor/empty.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ defmodule ExActor.Empty do
defmacro __using__(opts) do
quote do
@behaviour :gen_server
use ExActor.Common

@generated_funs MapSet.new

Expand Down
1 change: 1 addition & 0 deletions lib/exactor/gen_server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ defmodule ExActor.GenServer do
defmacro __using__(opts) do
quote do
use GenServer
use ExActor.Common

@generated_funs MapSet.new

Expand Down
50 changes: 26 additions & 24 deletions lib/exactor/operations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,8 @@ defmodule ExActor.Operations do
server_fun: server_fun(type),
interface_args: Macro.escape(interface_args(interface_matches, options), unquote: true),
gen_server_args: Macro.escape(gen_server_args(options, type, payload), unquote: true),
guard: Macro.escape(guard(options, :interface), unquote: true)
guard: Macro.escape(guard(options, :interface), unquote: true),
export_option: Macro.escape(options[:export], unquote: true)
] do
{interface_args, gen_server_args} =
unless type in [:multicall, :abcast] do
Expand All @@ -582,31 +583,32 @@ defmodule ExActor.Operations do
}
end

arity = length(interface_args)
unless private do
if guard do
def unquote(req_name)(unquote_splicing(interface_args))
when unquote(guard)
do
GenServer.unquote(server_fun)(unquote_splicing(gen_server_args))
end
interface_gen_server_args =
if type in [:multicall, :abcast] || export_option do
gen_server_args
else
def unquote(req_name)(unquote_splicing(interface_args)) do
GenServer.unquote(server_fun)(unquote_splicing(gen_server_args))
end
end
else
if guard do
defp unquote(req_name)(unquote_splicing(interface_args))
when unquote(guard)
do
GenServer.unquote(server_fun)(unquote_splicing(gen_server_args))
end
else
defp unquote(req_name)(unquote_splicing(interface_args)) do
GenServer.unquote(server_fun)(unquote_splicing(gen_server_args))
end
# Extract the server reference as first argument,
# And call `server_pid/1` on it inside the interface implementation.
# (But not in the function head)
[server_ref | gen_server_args_tail] = gen_server_args
server_pid_quote = quote(do: server_pid(unquote(server_ref)))
[server_pid_quote | gen_server_args_tail]
end

interface_body =
quote do
GenServer.unquote(server_fun)(unquote_splicing(interface_gen_server_args))
end

cond do
private == nil && guard == nil ->
def unquote(req_name)(unquote_splicing(interface_args)), do: unquote(interface_body)
private == nil && guard != nil ->
def unquote(req_name)(unquote_splicing(interface_args)) when unquote(guard), do: unquote(interface_body)
private != nil && guard == nil ->
defp unquote(req_name)(unquote_splicing(interface_args)), do: unquote(interface_body)
private != nil && guard != nil ->
defp unquote(req_name)(unquote_splicing(interface_args)) when unquote(guard), do: unquote(interface_body)
end
end
end
Expand Down
1 change: 1 addition & 0 deletions lib/exactor/strict.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ defmodule ExActor.Strict do
defmacro __using__(opts) do
quote do
use ExActor.Behaviour.Strict
use ExActor.Common

@generated_funs MapSet.new

Expand Down
1 change: 1 addition & 0 deletions lib/exactor/tolerant.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ defmodule ExActor.Tolerant do
defmacro __using__(opts) do
quote do
use ExActor.Behaviour.Tolerant
use ExActor.Common

@generated_funs MapSet.new

Expand Down