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 <[email protected]> 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
> [email protected]
> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>
_______________________________________________
zeromq-dev mailing list
[email protected]
http://lists.zeromq.org/mailman/listinfo/zeromq-dev

Reply via email to