I am writing a client-server application, and it uses POSIX poll
function to provide a form of concurrent client handling. Clients also have state and other related data, which is stored in a client structure.
My immediate problem is that when I get a hint from poll
to do I/O on a socket file descriptor that is associated with a client (conceptually), I have to actually match the file descriptor to its associated client data structure. Currently I do a O(n_clients)
lookup (my client data structure stores the descriptor), but I was wondering whether there exists a better alternative?
File descriptors are generally unique to each process, but they can be shared by child processes created with a fork subroutine or copied by the fcntl, dup, and dup2 subroutines.
File Descriptors are non-negative integers that act as an abstract handle to “Files” or I/O resources (like pipes, sockets, or data streams). These descriptors help us interact with these I/O resources and make working with them very easy. The I/O system is visible to a user process as a stream of bytes (I/O stream).
For most operating systems, a file descriptor (FD) is a small non-negative integer that helps in identifying an open file within a process while using input/output resources like network sockets or pipes. In a way, it can be considered as an index table of open files.
No. If there were, it would have to be tracked by the kernel, and looking up that data would therefore involve a system call. The cost of a system call is an order of magnitude more expensive than doing an O(n) lookup in user space.
How many clients are you dealing with at once? Unless it's on the order of hundreds or more, the cost of a lookup is going to be miniscule compared to the cost of doing any sort of I/O.
Instead of using an O(n) lookup, you could also just use an array indexed by the file descriptor, assuming you won't have more than a certain number of descriptors open at once. For example:
#define MY_MAX_FD 1024 // Tune this to your needs
void *per_fd_data[MY_MAX_FD];
void *get_per_fd_data(int fd)
{
assert(fd >= 0);
if(fd < MY_MAX_FD)
return per_fd_data[fd];
else
{
// Look up fd in a dynamic associative array (left as an exercise to the
// reader)
}
}
Cheapest is to just make a fixed-size array of connection structures, with {state, *context, ..., maybe callback functions} per entry, indexed by fd (=O(1)). Memory is cheap, and you can afford a few hundred or thousand file descriptors and table entries.
EDIT: You dont need to make it fixed size. If your pollstructure or fdset is fixed: make it fixed; otherwise use getdtablesize() or getrlimit() to get the number of entries to allocate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With