public SocketBase create_socket (int type_)
    {
        SocketBase s = null;
        slot_sync.lock ();
        try {
            if (starting) {
    
                starting = false;
                //  Initialise the array of mailboxes. Additional three slots are for
                //  zmq_term thread and reaper thread.
                opt_sync.lock ();
                int mazmq = max_sockets;
                int ios = io_thread_count;
                opt_sync.unlock ();
                slot_count = mazmq + ios + 2;
                slots = new Mailbox[slot_count];
                //alloc_assert (slots);
    
                //  Initialise the infrastructure for zmq_term thread.
                slots [term_tid] = term_mailbox;
    
                //  Create the reaper thread.
                reaper = new Reaper (this, reaper_tid);
                //alloc_assert (reaper);
                slots [reaper_tid] = reaper.get_mailbox ();
                reaper.start ();
    
                //  Create I/O thread objects and launch them.
                for (int i = 2; i != ios + 2; i++) {
                    IOThread io_thread = new IOThread (this, i);
                    //alloc_assert (io_thread);
                    io_threads.add(io_thread);
                    slots [i] = io_thread.get_mailbox ();
                    io_thread.start ();
                }
    
                //  In the unused part of the slot array, create a list of empty slots.
                for (int i = (int) slot_count - 1;
                      i >= (int) ios + 2; i--) {
                    empty_slots.add (i);
                    slots [i] = null;
                }
                
            }
    
            //  Once zmq_term() was called, we can't create new sockets.
            if (terminating) {
                ZError.errno(ZError.ETERM);
                return null;
            }
    
            //  If max_sockets limit was reached, return error.
            if (empty_slots.isEmpty ()) {
                ZError.errno(ZError.EMFILE);
                return null;
            }
    
            //  Choose a slot for the socket.
            int slot = empty_slots.pollLast();
    
            //  Generate new unique socket ID.
            int sid = max_socket_id.incrementAndGet();
    
            //  Create the socket and register its mailbox.
            s = SocketBase.create (type_, this, slot, sid);
            if (s == null) {
                empty_slots.addLast(slot);
                return null;
            }
            sockets.add (s);
            slots [slot] = s.get_mailbox ();
            
        } finally {
            slot_sync.unlock ();
        }
        
        return s;
    }