Erlang ETS insert/2 错误
Erlang ETS insert/2 error
我正在尝试创建一个可以访问 ETS 模块的简单 Erlang 进程。
我的源代码包括:
进程创建:
start_message_channel() ->
Table = ets:new(messages, [ordered_set, named_table]),
Channel = spawn(?MODULE, channel, []),
{Channel, {table, Table}}.
流程逻辑:
channel() ->
receive
{Sender, {send_message, {Message, Table}}} ->
ets:insert(Table, {message, Message}),
Sender ! {self(), {status, success}};
{Sender, {receive_message, Table}} ->
{message, Message} = ets:first(Table),
Sender ! {self(), {status, {success, Message}}};
_ ->
throw(incorrect_protocol_exception)
end.
与进程通信
send_message_to_message_channel({Channel, {table, Table}}, Message) ->
Channel ! {self(), {send_message, {Message, Table}}},
receive
{Channel, {status, success}} ->
io:format("Message sent!~n");
{Channel, {status, failure}} ->
io:format("Message failed to send!~n");
_ ->
throw(incorrect_protocol_exception)
end.
receive_message_from_message_channel({Channel, {table, Table}}) ->
Channel ! {self(), {receive_message, Table}},
receive
{Channel, {status, {success, Message}}} ->
io:format(Message);
{Channel, {status, failure}} ->
io:format("Message failed to receive!~n");
_ ->
throw(incorrect_protocol_exception)
end.
在 Erlang 终端中执行函数调用时,出现错误:
1> cd("C:/Users/dauma").
C:/Users/dauma
ok
2> c(message_channel).
{ok,message_channel}
3> Object = message_channel:start_message_channel().
{<0.59.0>,{table,messages}}
4> message_channel:send_message_to_message_channel(Object, "Hello World!").
=ERROR REPORT==== 19-May-2016::11:09:27 ===
Error in process <0.59.0> with exit value:
{badarg,[{ets,insert,[messages,"Hello World!"],[]},
{message_channel,channel,0,
[{file,"message_channel.erl"},{line,35}]}]}
谁能告诉我,问题出在哪里?
ETS tables 由 Erlang 进程拥有,并具有访问控制。默认情况下 table 是 protected
并且只能由拥有它的进程写入,尽管它可以从其他进程读取。
如果要从不同的进程读取和写入,请使用 public
。
Table = ets:new(messages, [ordered_set, named_table, public])
也可以使用private
,即只有所属进程可以读写
public
Any process may read or write to the table.
protected
The owner process can read and write to the table. Other processes can only read the table. This is the default setting for the access rights.
private
Only the owner process can read or write to the table.
在您的示例中,您在一个进程(调用 start_message_channel
的进程)中创建了 table,然后您尝试从另一个进程调用 ets:insert
:spawn(?MODULE, channel, [])
创建一个新进程,以 channel
作为其入口点。
因为您的 table 没有被标记为 public
,所以从其他进程调用 ets:insert
失败并返回 badarg
。
In general, the functions below will exit with reason badarg
if any argument is of the wrong format, if the table identifier is invalid or if the operation is denied due to table access rights (protected
or private
).
旁注:如果您使用 named_table
,从 ets:new
返回的值是 table 名称,因此您可以这样做:
-define(TABLE, messages).
% later...
?TABLE = ets:new(?TABLE, [named_table, ordered_set, protected])
...并且您不需要将返回值存储在状态中。
我正在尝试创建一个可以访问 ETS 模块的简单 Erlang 进程。
我的源代码包括:
进程创建:
start_message_channel() -> Table = ets:new(messages, [ordered_set, named_table]), Channel = spawn(?MODULE, channel, []), {Channel, {table, Table}}.
流程逻辑:
channel() -> receive {Sender, {send_message, {Message, Table}}} -> ets:insert(Table, {message, Message}), Sender ! {self(), {status, success}}; {Sender, {receive_message, Table}} -> {message, Message} = ets:first(Table), Sender ! {self(), {status, {success, Message}}}; _ -> throw(incorrect_protocol_exception) end.
与进程通信
send_message_to_message_channel({Channel, {table, Table}}, Message) -> Channel ! {self(), {send_message, {Message, Table}}}, receive {Channel, {status, success}} -> io:format("Message sent!~n"); {Channel, {status, failure}} -> io:format("Message failed to send!~n"); _ -> throw(incorrect_protocol_exception) end. receive_message_from_message_channel({Channel, {table, Table}}) -> Channel ! {self(), {receive_message, Table}}, receive {Channel, {status, {success, Message}}} -> io:format(Message); {Channel, {status, failure}} -> io:format("Message failed to receive!~n"); _ -> throw(incorrect_protocol_exception) end.
在 Erlang 终端中执行函数调用时,出现错误:
1> cd("C:/Users/dauma").
C:/Users/dauma
ok
2> c(message_channel).
{ok,message_channel}
3> Object = message_channel:start_message_channel().
{<0.59.0>,{table,messages}}
4> message_channel:send_message_to_message_channel(Object, "Hello World!").
=ERROR REPORT==== 19-May-2016::11:09:27 ===
Error in process <0.59.0> with exit value:
{badarg,[{ets,insert,[messages,"Hello World!"],[]},
{message_channel,channel,0,
[{file,"message_channel.erl"},{line,35}]}]}
谁能告诉我,问题出在哪里?
ETS tables 由 Erlang 进程拥有,并具有访问控制。默认情况下 table 是 protected
并且只能由拥有它的进程写入,尽管它可以从其他进程读取。
如果要从不同的进程读取和写入,请使用 public
。
Table = ets:new(messages, [ordered_set, named_table, public])
也可以使用private
,即只有所属进程可以读写
public
Any process may read or write to the table.protected
The owner process can read and write to the table. Other processes can only read the table. This is the default setting for the access rights.private
Only the owner process can read or write to the table.
在您的示例中,您在一个进程(调用 start_message_channel
的进程)中创建了 table,然后您尝试从另一个进程调用 ets:insert
:spawn(?MODULE, channel, [])
创建一个新进程,以 channel
作为其入口点。
因为您的 table 没有被标记为 public
,所以从其他进程调用 ets:insert
失败并返回 badarg
。
In general, the functions below will exit with reason
badarg
if any argument is of the wrong format, if the table identifier is invalid or if the operation is denied due to table access rights (protected
orprivate
).
旁注:如果您使用 named_table
,从 ets:new
返回的值是 table 名称,因此您可以这样做:
-define(TABLE, messages).
% later...
?TABLE = ets:new(?TABLE, [named_table, ordered_set, protected])
...并且您不需要将返回值存储在状态中。