5

In the tutorial provided at: http://www.erlang.org/doc/tutorial/cnode.html

There is the following example:


/* cnode_s.c */
#include 
#include 
#include 
#include 
#include "erl_interface.h"
#include "ei.h"
#define BUFSIZE 1000
int main(int argc, char **argv) {
  int port;                                /* Listen port number */
  int listen;                              /* Listen socket */
  int fd;                                  /* fd to Erlang node */
  ErlConnect conn;                         /* Connection data */
  int loop = 1;                            /* Loop flag */
  int got;                                 /* Result of receive */
  unsigned char buf[BUFSIZE];              /* Buffer for incoming message */
  ErlMessage emsg;                         /* Incoming message */
  ETERM *fromp, *tuplep, *fnp, *argp, *resp;
  int res;
  port = atoi(argv[1]);
  erl_init(NULL, 0);
  if (erl_connect_init(1, "secretcookie", 0) == -1)
    erl_err_quit("erl_connect_init");
  /* Make a listen socket */
  if ((listen = my_listen(port)) 

I suspect that erl_receive_msg is a blocking call, and I don't know how to overcome this. In C network programming there is the "select" statement but in the Erlang EI API I don't know whether there is such a statement.

Basically I want to build a C node, that continuously sends messages to Erlang nodes. For simplicity suppose there is only one Erlang node.

The Erlang node has to process the messages it receives from the C node. The Erlang node is not supposed to ensure that it has received the message, not does it have to reply with the result of processing. Therefore once the message is sent I don't care about it faith.

One might think that one could modify the code as:

...
if (emsg.type == ERL_REG_SEND) {
    ...
    while(1) { 
        //generate tuple
        erl_send(fd, fromp, tuple);
        //free alloc resources
    }
    ...
}

This will produce an infinite loop in which we produce and consume (send) messages. But there is an important problem: if I do this, then the C node might send too many messages to the Erlang node (so there should be a way to send a message from the Erlang node to the C node to slow down), or the Erlang node might think that the C node is down.

I know that the questions must be short an suite (this is long and ugly), but summing up:

What mechanism (procedure call, algorithm) one might use to develop an eager producer in C for a lazy consumer in Erlang, such that both parties are aware of the underlying context ?

ndim
  • 35,870
  • 12
  • 47
  • 57
user237855
  • 51
  • 3

3 Answers3

2

I use Port Drivers myself for the case you are describing (haven't touched the C nodes because I'd rather have more decoupling).

Have a look at the Port Driver library for Erlang: EPAPI. There is a project that leverages this library: Erland DBus.

jldupont
  • 93,734
  • 56
  • 203
  • 318
  • The problem is that the producer will be the C node and the Erlang Node will be the consumer. I've considered the idea of using a port, but calling in a continuous loop the port driver's service doesn't seem the best way to do this. – user237855 Dec 23 '09 at 20:29
  • @zalmoxis: there are many different ways to address this situation, one of which might be to use a "token based credit algorithm". The "consumer node" sends "credits" to the producer node. Each "send" requires a "credit": when there is no more, the "producer" must wait for a next "delivery" of credits. – jldupont Dec 23 '09 at 20:32
  • @zalmoxis: the "token based shaper" I describe above can easily be implemented on the "producer" side (written in C) whilst it is equally trivial to add support for this scheme on the Erlang side. Since you are already for "pain" using "C nodes", then I know you can take on Port Drivers. Cheers and have fun! ( anyhow, as always, consider my contribution as a suggestion for your consideration ). – jldupont Dec 23 '09 at 20:34
1

Did you check the ei_receive_msg_tmo function? I suppose it works similar to the receive after construct of Erlang, so if you set timeout to 0, it will be non-blocking.

I believe erl_interface is deprecated, and ei should be used instead. This might be a complete misinformation though...

Zed
  • 57,028
  • 9
  • 76
  • 100
  • Thanks, I am currently testing it. Please note that by calling ei_receive_msg_tmo with timeout 0 it will become blocking. – user237855 Dec 23 '09 at 21:01
  • Okay. So apparently the non-timeout functions fall back to the timeout ones with ms=0. That's why ms=0 becomes blocking (see the ei_read_t() function erl_interface/src/misc/ei_portio.c). I would call this a victory of laziness over functionality :) – Zed Dec 23 '09 at 21:19
1

you need to take a closer look at the tutorial link that you posted. (search for "And finally we have the code for the C node client.") You will see that the author provided a client cnode implementation. It looks rational.

Richard
  • 10,122
  • 10
  • 42
  • 61