/// <summary>
/// Create and return a new socket of the given type, and initialize this Ctx if this is the first one.
/// </summary>
/// <param name="type">the type of socket to create</param>
/// <returns>the newly-created socket</returns>
/// <exception cref="TerminatingException">Cannot create new socket while terminating.</exception>
/// <exception cref="NetMQException">Maximum number of sockets reached.</exception>
/// <exception cref="TerminatingException">The context (Ctx) must not be already terminating.</exception>
public SocketBase CreateSocket(ZmqSocketType type)
{
lock (m_slotSync)
{
if (m_starting)
{
m_starting = false;
// Initialise the array of mailboxes. Additional three slots are for
// zmq_term thread and reaper thread.
int ios;
int mazmq;
lock (m_optSync)
{
mazmq = m_maxSockets;
ios = m_ioThreadCount;
}
m_slotCount = mazmq + ios + 2;
m_slots = new IMailbox[m_slotCount];
//alloc_Debug.Assert(slots);
// Initialise the infrastructure for zmq_term thread.
m_slots[TermTid] = m_termMailbox;
// Create the reaper thread.
m_reaper = new Reaper(this, ReaperTid);
//alloc_Debug.Assert(reaper);
m_slots[ReaperTid] = m_reaper.Mailbox;
m_reaper.Start();
// Create I/O thread objects and launch them.
for (int i = 2; i != ios + 2; i++)
{
var ioThread = new IOThread(this, i);
//alloc_Debug.Assert(io_thread);
m_ioThreads.Add(ioThread);
m_slots[i] = ioThread.Mailbox;
ioThread.Start();
}
// In the unused part of the slot array, create a list of empty slots.
for (int i = m_slotCount - 1; i >= ios + 2; i--)
{
m_emptySlots.Push(i);
m_slots[i] = null;
}
}
// Once zmq_term() was called, we can't create new sockets.
if (m_terminating)
{
string xMsg = string.Format("Ctx.CreateSocket({0}), cannot create new socket while terminating.", type);
throw new TerminatingException(innerException: null, message: xMsg);
}
// If max_sockets limit was reached, return error.
if (m_emptySlots.Count == 0)
{
#if DEBUG
string xMsg = string.Format("Ctx.CreateSocket({0}), max number of sockets {1} reached.", type, m_maxSockets);
throw NetMQException.Create(xMsg, ErrorCode.TooManyOpenSockets);
#else
throw NetMQException.Create(ErrorCode.TooManyOpenSockets);
#endif
}
// Choose a slot for the socket.
int slot = m_emptySlots.Pop();
// Generate new unique socket ID.
int socketId = Interlocked.Increment(ref s_maxSocketId);
// Create the socket and register its mailbox.
SocketBase s = SocketBase.Create(type, this, slot, socketId);
m_sockets.Add(s);
m_slots[slot] = s.Mailbox;
//LOG.debug("NEW Slot [" + slot + "] " + s);
return s;
}
}