I am writing an application in C for linux, which uses 2 separate third-party libraries. Both libraries are asynchronous and use select(). They also provide an API which returns the file descriptors they wait on. My intention is to pass these into my own select() and then return control back to whichever library when their own fd values are set.
I think I've got most of it written, but I have trouble at the point where the select() parameters are concerned: Both libraries do not give individual file descriptors, but pointers to their read and write fd_sets. I need to combine the returned fd_sets from these libraries into one fd_set for read, one fd_set for write, etc.
Any suggestions on how I can combine 2 fd_sets into one resulting fd_set?
Addendum Sorry! I should have been clearer.. these libraries only return the fd_sets... I don't know the number of FDs in each set so that I can do a for loop and set each FD individually.. is there a simple way of determining this given just an fd_set?
C code which doesn't depend on the implementation of fd_set
:
void Fdset_Add(fd_set *Out, fd_set const *In, int InNfds)
{
for(i = 0; i < InNfds; i++)
{
if(i < InNfds && FD_ISSET(i, In))
FD_SET(i, Out);
}
}
int Fdset_Merge(fd_set *Out, fd_set const *In1, int NFds1, fd_set const *In2, int NFds2)
{
FD_ZERO(Out);
Fdset_Add(Out, In1, Nfds1);
Fdset_Add(Out, In2, Nfds2);
return Nfds1 > Nfds2 ? Nfds1 : Nfds2;
}
int Fdset_Filter(fd_set const *Result, int ResultNfds, fd_set *ToFilter, int NfdsToFilter)
{
int i;
int Retval;
Retval = 0;
for(i = 0; i < ResultNfds; i++)
{
if(i < NfdsToFilter && FD_ISSET(i, ToFilter))
{
if(! FD_ISSET(i, Result))
FD_CLR(i, ToFilter);
else
Retval++;
}
}
return Retval;
}
void Fdset_Split(fd_set const *Result, int ResultNfds, fd_set *In1, int Nfds1, int *Count1, fd_set *In2, int Nfds2, int *Count2)
{
*Count1 = Fdset_Filter(Result, ResultNfds, In1, Nfds1);
*Count2 = Fdset_Filter(Result, ResultNfds, In1, Nfds2);
}
You can set up your own fd_set
by looping over all possible file descriptors that each library could possibly have open and in each of their returned sets and set your's accordingly. It's a bit brute-force but the select interface is unfortunately quite primitive. For example
fd_set *lib1_read_fds, *lib2_read_fds;
int fd;
fdset my_fd_set;
FD_CLR(&my_fd_set);
for (fd = 0; fd < FD_SETSIZE; fd++) {
if (FD_ISSET(fd, lib1_read_fds) || FD_ISSET(fd, lib2_read_fds)) {
FD_SET(fd, &my_fd_set);
}
}
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