[zeromq-dev] Initial support for zmq_poll() under Java

Alexander T mittspamkonto at gmail.com
Fri Feb 26 13:37:13 CET 2010


Just wanted to add that the enum approach makes more sense anyway,
since the zmq context creates the sockets. Clients should not
instantiate socket types explicitly. Typical builder pattern.

I also think that the term 'context' becomes a misnomer in the Java
driver. I would rather have a the 'Zmq' class with an internal
context. More like the second approach thus.

In principal:

class ZmqContext {
   //internal pointer to c context
   private final long contextPtr;
   public ZmqContext {
        contextPtr = zmq_init(...);
   }

   public long getCPointer() {
        return contextPtr;
   }
}

class Zmq {
   private final ZmqContext zc;
   public Zmq() {
          lazyLoadLib('zmq');
          zc = new ZmqContext();
   }

   public ISocket createSocket(enum sockType) {
          return new MultiSocket(zc, sockType);
   }
}

interface ISocket {
     public IResult send();
    //etc
}

package private class MultiSocket implements ISocket {
     private enum sockType;
     public MultiSocket(ZmqContext context, SockType sockType) {
          this.socketHandle = zmq_create_socket(context.getCPointer,
sockType.C_VALUE);
     }

     public IResult send(data) {
           return new MultiResult(zmq_send(data, ....));
     }
}

etc...

The client would then only have to do:
Zmq zmq = new Zmq();
ISocket sock = zmq.createSocket(SocketType.XX);
sock.send(data);

The context passing becomes transparent. You have one Zmq instance per
application (I assumed that you can have multiple zmq intances per JVM
/ executable).

The 'class per socket type' is only useful if you want to add
type-specific code in the language wrapper, which I don't think should
be needed in most cases.

Just my 2 cents.

Alexander T

On 2/26/10, Martin Sustrik <sustrik at 250bpm.com> wrote:
> Brian Granger wrote:
>
>> * For an OO language, it is awkward to instantiate a Socket by hand
>> when you have to pass the Context:
>>
>> s = Socket(ctx, zmq.REP)
>>
>> A better approach would be to let the context create the Socket:
>>
>> ctx.create_socket(zmq.REP)
>>
>> That way, you are sure to get the ctx argument correct.  This is
>> implemented in the
>> Python binding.
>
> Sure, why not.
>
>> * It is tempting to make the different socket types subclasses:
>>
>> SocketBase
>> RepSocket
>> ReqSocket
>> P2PSocket
>>
>> Rather than using the zmq.REP|REQ... flags.  I did not implement this
>> as it seemed to
>> go too afar from the C/C++ bindings.
>
> I would strongly suggest not to go this way.
>
> Socket types & socket options are deliberately designed as 0MQ extension
> points, meaning that while ABI stays stable, new functionality can be
> added via new socket types/options.
>
> Therefore, there should be no socket-type- or option- specific code in
> the bindings. That way new functionality can be accessed without a
> change to the API (put aside adding new constants).
>
> Have a look how BSD socket API is designed. I believe they've got this
> thing exactly right and that's one of the main reasons why BSD socket
> API became as ubiquitous as it is today.
>
>> * I need the ability to bind a Socket to a random port number (0).
>> Because ZMQ doesn't support
>> this, I implemented a bind_to_random_port method that tries random
>> ports in a range until
>> it finds one and then returns that port number.
>>
>> http://github.com/ellisonbg/pyzmq/blob/master/zmq/_zmq.pyx#L287
>
> Hm, this one is interesting, however, I am afraid that allowing for this
> kind of functionality breaks the big picture.
>
> In short, the idea is that messaging "channels" (in this case ports) are
> assigned more or less statically. Business "channel" (say "NASDAQ quote
> feed") is mapped to specific "address" (say "port 3456").
>
> Think of assigning IP numbers or domain names. These are more or less
> statically defined and thus allow for resolution on Internet scale. With
> dynamically assigned addresses this kind of resolution is not possible
> AFAICS.
>
> This is an area for future research though, so feel free to discuss.
>
>> * My interface to poll in modeled on Python's built-in select.poll module:
>>
>> It has a Poller class which you create and then call register to add
>> fds/sockets:
>>
>> p = Poller()
>> p.register(s1)
>> p.register(s2)
>> p.poll(timeout=10)
>> p.unregister(s1)
>>
>> * I have added additional methods to the Socket object to serialize
>> Python objects and send messages in various formats:  send_json,
>> recv_json (json) and send_pyobj, recv_pyobj (pickle).
>>
>> Overall, the core API of the Python bindings follows the C/C++ very
>> closely though.
>>
>> I am willing to change some of the core API of the Python bindings if
>> needed but I do think it is important
>> for each language to create an API that follows the spirit of the
>> language.
>
> Ack. API for each language should place as little barrier for adoption
> by users of the language as possible. At the same time is should keep as
> close to underlying C API as to make it easy for users to refer to C API
> documentation.
>
> Martin
>
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>



More information about the zeromq-dev mailing list