2016-05-19 11 views
0

ETSモジュールへのアクセスで簡単なErlangプロセスを作成しようとしています。Erlang ETS挿入/ 2エラー

私のソースコードが含まれています:

  1. プロセスの作成:

    start_message_channel() -> 
        Table = ets:new(messages, [ordered_set, named_table]), 
        Channel = spawn(?MODULE, channel, []), 
        {Channel, {table, Table}}. 
    
  2. プロセスロジック:プロセス

    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. 
    
  3. コミュニケーション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}]}]} 

は、誰がどこであるかもしれない、問題を教えてください。

答えて

6

ETSテーブルはErlangプロセスが所有し、アクセスコントロールを持っています。デフォルトではテーブルはprotectedであり、それを所有するプロセスによってのみ書き込むことができますが、他のプロセスから読み取ることができます。

異なるプロセスから読み書きする場合は、publicを使用してください。

Table = ets:new(messages, [ordered_set, named_table, public]) 

また、唯一所有しているプロセスが読み書きできることを意味しprivateを、使用することができます。 the documentationパー

  • 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.

あなたの例では、1つのプロセス内のテーブルを(1がstart_message_channelを呼び出す)を作成し、次にあなたが別のプロセスからets:insertを呼び出そう:spawn(?MODULE, channel, [])は、新しいプロセスを作成し、エントリポイントとしてchannelがあります。

テーブルがpublicとマークされていないため、ets:insertへの呼び出しは、他のプロセスからbadargで失敗します。 the documentation, againパー

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から返さテーブル名ですので、あなたがこれを行うことができます:

-define(TABLE, messages). 

% later... 
?TABLE = ets:new(?TABLE, [named_table, ordered_set, protected]) 

...戻り値をstateに格納する必要はありません。

+0

ありがとうございました!あなたが示唆した小さな変更の後、すべてが魅力のように動作します!理解を深めるために、私の例では、テーブルの更新を作成したのと同じプロセスではないことを伝えることができますか? –

+0

#1でテーブルを作成し、チャネル/ 0を実行するプロセスを生成します。それは挿入を行うプロセスなので、プライベートでは動作しません。 –

+0

はい、デフォルトは 'protected'です。 – rvirding