boolRemoveClient(constcCallback*a_Client);// Returns true if removed, false if not found
boolRemoveSocket(constcSocket*a_Socket);// Returns true if removed, false if not found
boolHasClient(constcCallback*a_Client)const;
boolHasSocket(constcSocket*a_Socket)const;
boolNotifyWrite(constcCallback*a_Client);// Returns true if client handled by this thread
boolWrite(constcSocket*a_Socket,constAString&a_Data);// Returns true if socket handled by this thread
boolStopReading(constcCallback*a_Client);// Returns true if client handled by this thread
boolQueueClose(constcSocket*a_Socket);// Returns true if socket handled by this thread
boolStart(void);// Hide the cIsThread's Start method, we need to provide our own startup to create the control socket
boolIsValid(void)const{returnm_ControlSocket2.IsValid();}// If the Control socket dies, the thread is not valid anymore
private:
cSocketThreads*m_Parent;
// Two ends of the control socket, the first is select()-ed, the second is written to for notifications
cSocketm_ControlSocket1;
cSocketm_ControlSocket2;
// Socket-client-packetqueues triplets.
// Manipulation with these assumes that the parent's m_CS is locked
structsSlot
{
cSocket*m_Socket;
cCallback*m_Client;
AStringm_Outgoing;// If sending writes only partial data, the rest is stored here for another send
boolm_ShouldClose;// If true, the socket is to be closed after sending all outgoing data
};
sSlotm_Slots[MAX_SLOTS];
intm_NumSlots;// Number of slots actually used
virtualvoidExecute(void)override;
voidAddOrUpdatePacket(inta_Slot,cPacket*a_Packet);// Adds the packet to the specified slot, or updates an existing packet in that queue (EntityMoveLook filtering)
voidPrepareSet(fd_set*a_Set,cSocket::xSocket&a_Highest);// Puts all sockets into the set, along with m_ControlSocket1
voidReadFromSockets(fd_set*a_Read);// Reads from sockets indicated in a_Read
voidWriteToSockets(fd_set*a_Write);// Writes to sockets indicated in a_Write
voidRemoveClosedSockets(void);// Removes sockets that have closed from m_Slots[]