Erlang ETS 插入/2 错误
Posted
技术标签:
【中文标题】Erlang ETS 插入/2 错误【英文标题】:Erlang ETS insert/2 error 【发布时间】:2016-09-16 00:20:13 【问题描述】:我正在尝试创建一个可以访问 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]]
谁能告诉我,问题出在哪里?
【问题讨论】:
【参考方案1】:ETS 表由 Erlang 进程拥有,并具有访问控制。默认情况下,该表为protected
,只能由拥有它的进程写入,但可以从其他进程读取。
如果您想从不同的进程读取和写入,请使用public
。
Table = ets:new(messages, [ordered_set, named_table, public])
你也可以使用private
,也就是说只有拥有的进程可以读写。
每the documentation:
public
任何进程都可以读取或写入表。protected
所有者进程可以对表进行读写。其他进程只能读取该表。这是访问权限的默认设置。private
只有所有者进程可以读取或写入表。
在您的示例中,您在一个进程中创建表(调用start_message_channel
的进程),然后尝试从另一个进程调用ets:insert
:spawn(?MODULE, channel, [])
创建一个新进程,channel
为它的入口点。
由于您的表未标记为public
,因此从其他进程调用ets:insert
失败并显示badarg
。
每the documentation, again:
一般来说,如果任何参数格式错误、表标识符无效或由于表访问权限(
protected
或private
)。
旁注:如果你使用named_table
,从ets:new
返回的值是表名,所以你可以这样做:
-define(TABLE, messages).
% later...
?TABLE = ets:new(?TABLE, [named_table, ordered_set, protected])
...并且您不需要将返回值存储在状态中。
【讨论】:
感谢您的回答!在您建议的小改动之后,一切都像魅力一样!为了更好地理解,你能告诉我,在我的例子中,创建表的过程不是更新它吗? 您在#1 中创建表,然后生成一个进程来运行通道/0。这就是插入的过程,因此私有化不起作用。 是的,但默认是protected
。
@rvirding, true(我不记得了,所以我倾向于直言不讳);更新了我的答案。以上是关于Erlang ETS 插入/2 错误的主要内容,如果未能解决你的问题,请参考以下文章