In article <200506010140.j511edY4012889 / sharui.nakada.niregi.kanuma.tochigi.jp>,
  nobu / ruby-lang.org writes:

> こんな感じでしょうか。

基本的な方針は「なぜか余計にメモリを確保しておいて動いたらラッキー」な
ので、今まで参照していなかった FD_SETSIZE は今さら参照しなくても書ける
はずなんじゃないかと思います。

> void
> rb_fd_zero(fds)
>     rb_fdset_t *fds;
> {
>     if (fds->fdset) {
> 	MEMZERO(fds->fdset, fd_mask, howmany(fds->maxfd, NFDBITS));
> 	if (sizeof(fd_set) * CHAR_BIT != howmany(FD_SETSIZE, NFDBITS) * NFDBITS)
> 	    FD_ZERO(fds->fdset);
>     }
> }

FD_ZERO による初期状態が 0 の並びでない可能性を考慮するなら、FD_ZERO
は常に行うべきでしょう。

    if (fds->fdset) {
	MEMZERO(fds->fdset, fd_mask, howmany(fds->maxfd, NFDBITS));
	FD_ZERO(fds->fdset);
    }

> void
> rb_fd_set(n, fds)
>     int n;
>     rb_fdset_t *fds;
> {
>     int m, o;
>
>     if (n < FD_SETSIZE)
> 	m = sizeof(fd_set);
>     else
> 	m = howmany(n + 1, NFDBITS) * NFDBITS;
>     if (fds->maxfd <= FD_SETSIZE)
> 	o = sizeof(fd_set);
>     else
> 	o = howmany(fds->maxfd, NFDBITS) * NFDBITS;
>
>     if (m > o) {
> 	fds->fdset = realloc(fds->fdset, m);
> 	memset((char *)fds->fdset + o, 0, m - o);
>     }
>     if (n >= fds->maxfd) fds->maxfd = n + 1;
>     FD_SET(n, fds->fdset);
> }

FD_SETSIZE を避けるならこうかなぁ。

    int m, o;
    m = howmany(n + 1, NFDBITS) * NFDBITS;
    if (m < sizeof(fd_set))
 	m = sizeof(fd_set);
    o = howmany(fds->maxfd, NFDBITS) * NFDBITS;
    if (o < sizeof(fd_set))
	o = sizeof(fd_set);

    if (m > o) {
	fds->fdset = realloc(fds->fdset, m);
	memset((char *)fds->fdset + o, 0, m - o);
    }
    if (n >= fds->maxfd) fds->maxfd = n + 1;
    FD_SET(n, fds->fdset);

> void
> rb_fd_clr(n, fds)
>     int n;
>     rb_fdset_t *fds;
> {
>     if (n > FD_SETSIZE && n >= fds->maxfd) return;
>     FD_CLR(n, fds->fdset);
> }

これもこうですかねぇ。

    if (n >= fds->maxfd) return;
    FD_CLR(n, fds->fdset);

> int
> rb_fd_isset(n, fds)
>     int n;
>     const rb_fdset_t *fds;
> {
>     if (n > FD_SETSIZE && n >= fds->maxfd) return 0;
>     return FD_ISSET(n, fds->fdset);
> }

これも。
    if (n >= fds->maxfd) return 0;
    return FD_ISSET(n, fds->fdset);

> void
> rb_fd_copy(dst, src, max)
>     rb_fdset_t *dst;
>     const fd_set *src;
>     int max;
> {
>     int size = sizeof(fd_set);
>     if ((dst->maxfd = max) > FD_SETSIZE) {
> 	size = howmany(max, NFDBITS) * NFDBITS;
>     }
>     dst->fdset = realloc(dst->fdset, size);
>     memcpy(dst->fdset, src, size);
> }

これはこうかなぁ。

    int size = howmany(max, NFDBITS) * NFDBITS;
    if (size < sizeof(fd_set))
        size = sizeof(fd_set);
    dst->fdset = realloc(dst->fdset, size);
    memcpy(dst->fdset, src, size);

>> # Windows の fd_set は違うというので探したら、
>> # http://msdn.microsoft.com/library/en-us/winsock/winsock/fd_set_2.asp
>> # を見る限りは MEMZERO だけでよさそうですねぇ。
>
> そもそもwinsockがFD_SETSIZE以上を見てくれるかどうか、というより
> もWaitForMultipleObjects()が見てくれなさげ。

MEMZERO だけでいいというのは、FD_ZERO と同等の効果がありそうだ、という
意味です。

FD_SETSIZE以上のサポートを広げるという意味では、poll にする意味が有る
かというのが興味の有るところなのですが、Windows は救えなさそうですね。
(そもそも Windows に poll があるのかどうか知りませんが)

poll にすれば救える環境って存在するのかなぁ?
-- 
[田中 哲][たなか あきら][Tanaka Akira]