Path: utzoo!attcan!uunet!samsung!usc!elroy.jpl.nasa.gov!jpl-devvax!lwall From: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Newsgroups: comp.lang.perl Subject: Re: "comparing bitmasks" Message-ID: <10128@jpl-devvax.JPL.NASA.GOV> Date: 27 Oct 90 06:20:49 GMT References: <1990Oct26.182652.13422@uvaarpa.Virginia.EDU> Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Organization: Jet Propulsion Laboratory, Pasadena, CA Lines: 74 In article <1990Oct26.182652.13422@uvaarpa.Virginia.EDU> eichin@apollo.com writes: : I'm using select to wait for a collection of file descriptors. I build : masks $rin and $win: : @fdnames=(F1,F2,F3,F4,F5,F6,F7,F8,F9,F10); : foreach(@fdnames) { : $tin = ''; vec($tin,fileno($_),1) = 1; : if($mode{$_} eq "writewait") { $win = $win | $tin; } : if($mode{$_} eq "readwait") { $rin = $rin | $tin; } : } : $nfound = select($rin,$win,undef,undef); If I were doing this, I'd probably maintain my $rin and $win over multiple calls, and just vec in and out the proper bits only when necessary. : The question: how do I check which bits are set (ie which filehandles : are available for read or write)? I have a similar loop, which does : ($win & $tin) and checks it, but what is the right way to check? : ($win & $tin) is always true. In fact, I tried a few tests (setting : $xx=$foo & $bar), and found the following were *always* true: : if($xx) Since $xx is a string and not a number, this is equivalent to $xx ne "". (Unless $xx is 1 byte long, and bits 32 and 16 are set, making "0"...) : if($xx == 0) This would have the unfortunate effect of turning $xx numeric. It's only true occasionally, depending on the bit patterns--you'd have to have at least 3 bits set to get a digit between 1 and 9. : if($xx eq "") I suspect that one was always false. : if(defined($xx)) : : throwing in a ($vxx)=unpack("c",$xx) made : if($vxx) : true as long as the bit being masked was less than 8 (ie in the first : byte, which make sense...) It should be true even if the bit is 8 or above--the null string is supposed to be true. If it's not, it's a bug. When I say $foo = "\0\1"; if ($foo) {print "True";} it prints True. : What I finally got to work was testing : if(($rin & $tin) eq $tin) That's reasonable, but why not just if (vec($rin,fileno($_),1)) : It seems to work even when vec($tin,$x,1)=1 for $x>8, so it isn't : bothered by intervening nulls. However, this behavior isn't hinted at : in the manual page (it should probably be mentioned in the select : example.) Well, it's hinted at under vec(), but I'll agree it could be clearer. A vec bitstring is just a string that has arbitrary bits set in it, the first 8 bits in the first byte, the second 8 bits in the second byte, and so on. So a bitstring of n 0 bits is going to consist of roughly n/8 null bytes. Thus, if you have lots of bits to scan, you can search for the first non-zero bit like this: $rin =~ /[^\0]/ && $minbit = length($`) * 8; $minbit++ until vec($rin,$minbit,1); Most applications won't have enough zero bits to worry about that, tho. Larry