July, 2009

  • The Old New Thing

    Polling by sleeping versus polling by waiting with a timeout


    Commenter Francois Boucher asks it's better to write a background worker thread that polls with Sleep() and a flag, or polls by waiting for an event with a timeout?

    // method A
    while (fKeepGoing) {
     .. a little work ..
    // method B
    do {
     .. a little work ..
    } while (WaitForSingleObject(hEvent, 50) == WAIT_TIMEOUT);

    "Which scenario is better? The first one uses only 1 handle for the thread. The second one will use 2. But is the first scenario wasting more thread time? Is it worth using the event (kernel object)?"

    Yeah, whatever.

    I don't quite understand why you want to pause every so often. Why not just do the work at low priority? When there are more important things to do, your background thread will stop doing whatever it's doing. When there is an available CPU, then your background thread will do its thing as fast as it can (until something with higher priority arrives).

    The only thing I can think of is that by adding the pauses, your program won't look like it's consuming 100% CPU while the background processing is going on. Which is true, but then again, that's not much consolation. "Wow, with these changes, my spell check takes only 10% of the CPU. But then again, it also takes 10 times as long." Is that an improvement? You made your customer wait ten times as long for the document to be spell checked. That's ten times less battery life for your laptop.

    And generally speaking, polling should be avoided because it carries negative consequences for system performance. So we're basically asking, "Which is better, hammering with a screwdriver or hammering with pliers?"

    But let's say for the sake of argument that this "back off periodically" polling loop is actually the right design, and the only argument is which of the above two methods is "better" in terms of the criteria listed above (handles, thread time).

    It still doesn't matter.

    Method A has one fewer handle, but one more flag. So the total number of things you have to keep track of is the same either way.

    "Oh, but I save the overhead of an additional handle."

    Dude, you're already burning a thread. A single handle to an event is noise compared to the cost of a thread.

    "But I save the cost of validating the handle and following the reference to the underlying kernel object."

    Dude, you're about to go to sleep for 50 milliseconds. Saving a few thousand clocks is noise compared to 50 milliseconds.

    The flag method does have some other problems, none of which are deal-breaking, but are things to bear in mind.

    First, that flag that you're checking. There's no synchronization on that variable, so the background thread may run a smidge longer than necessary because the change hasn't yet propagated to the CPU running the loop. Similarly, the sleep loop does take a little longer to notice that it should stop working. If the fKeepGoing flag is set to FALSE during the sleep, the sleep will still run to completion before the loop finds out.

    In the grand scheme of things, however, the extra 50 to 100 milliseconds are probably not a big deal. The background thread is a little slow to shut down, that's all. The user will probably not even notice that the CPU meter was higher than normal for an additional tenth of a second. After all, the typical human reaction time is 100 milliseconds anyway.

    I'm assuming that the code that signals the background thread doesn't sit around waiting for the background thread to clean up. If it does, then this 100ms delay may start to combine with other delays to turn into something the user may start to notice. A tenth of a second here, a tenth of a second there, soon you may find yourself accumulating a half second's delay, and that's a delay the human brain can perceive.

  • The Old New Thing

    Your debugging code can be a security hole: Contest tickets


    Last year, the Microsoft cafeterias ran a promotion which involved scratch-off tickets and prizes ranging from a free bagel to a new Zune to free airplane tickets. But it turns out that the people who ran the contest left some debugging code behind that became a security hole.

    As people compared notes on what they did or didn't win, they noticed that the tickets all looked identical save for the scratch-off area (naturally) and some tiny numbers printed in the corner of the back of the card. After some study, it became clear that all the losing tickets had a code that ended in 01, all the tickets for a free bagel ended in 18, and so on. If you went to the contest rules and regulations Web site, you'd find the legally mandated odds of winning disclosure, and the table just so happened to have no prize as the first item in the table and free bagel as the eighteenth. Further comparisons with other winning tickets confirmed that you could tell ahead of time what prize you were going to win by just looking at the last two digits of the number printed on the back of the card.

    This is another example of how your debugging code can be a security hole. In this case, the code printed on the backs of the cards were probably added for quality control purposes, so that the contest managers could ensure that the right number of winning tickets were printed and so that the "big ticket" prizes would be evenly distributed among the participating cafeterias.

    But it also meant that everybody participating in the contest knows which are the winning tickets.

  • The Old New Thing

    How do I quickly position two windows side by side?


    Commenter n/a posted a laundry list of feature requests. I'm not going to address all of them here (though I inadvertently addressed one of them a while ago). But today I'm going to address request number two, "A simple switch to create two windows, one alongside the other, vertically split."

    That feature has been around since Windows 95, possibly even before that but I haven't bothered to check.

    In the taskbar, click the button for the first window you want to position, then hold the Ctrl key and right-click the button for the second window. Select Tile Vertically. Bingo, the two windows are positioned side by side.

    (If you pick Tile Horizontally then they appear one above the other.)

    Of course, the upcoming Windows 7 makes this operation much easier with a set of window-positioning features that collectively are known as Snap. Just drag one window to the left edge of the screen, and drag the other to the right edge of the screen. But what if you don't want the windows to auto-dock? We'll pick that up next time.

    Bonus chatter: In case you missed it, the Engineering Windows 7 team blog the history of window arrangement in Windows in a multi-part series: Part 1, Part 2, and Part 3: Aero Snap.

  • The Old New Thing

    A 32-bit application can allocate more than 4GB of memory, and you don't need 64-bit Windows to do it


    Commenter Herb wondered how a 32-bit program running on 64-bit Windows can allocate more than 4GB of memory. Easy: The same way it allocates more than 4GB of memory on 32-bit Windows!

    Over a year before Herb asked the question, I had already answered it in the tediously boring two-week series on the myths surrounding the /3GB switch. Here's a page that shows how you can allocate more than 2GB of memory by using shared memory (which Win32 confusingly calls file mappings). That code fragment allocated 4GB of memory at one go, and then accessed it in pieces (because a 32-bit program can't map an entire 4GB memory block at one go). To allocate more, either make the number bigger in the call to CreateFileMapping or just call CreateFileMapping multiple times.

    The following week, I talked about how you can use AWE to allocate physical pages. Again, you can allocate as much memory as you like, but if you allocate enormous amounts of memory, you will probably not be able to map them all in at once.

    The claims of the program are true, but 64-bit Windows wasn't necessary for the program to accomplish what it claims. It's like Dumbo and the magic feather. "Dumbo can fly with the magic feather in his trunk." Well, yeah, but he didn't actually need the feather.

    (On the other hand, 64-bit Windows certainly makes it more convenient to use more than 4GB of memory, since you can map the memory into your address space all at once and use normal pointers to access it.)

  • The Old New Thing

    Attack of the rogue feature: Oh no, where did my Explorer icon labels go?


    A customer reported that on Windows Vista, if you hold down the shift key and repeatedly click the View button in the command bar of an Explorer window, you will eventually reach a state where all the labels under the icons have disappeared! Where did they go, and how do I get them back?

    Congratulations, you stumbled across a rogue feature.

    One of the developers who worked on Windows XP decided to add a cute shortcut: Holding down the shift key when switching to Thumbnail mode will cause the labels to disappear. (At least, that was the intent of the rogue feature, but it so happens that as a side effect, the hold the shift key to remove labels shortcut also takes effect during certain other operations, because the shift key test was made in a shared worker function.)

    Great, now that they're gone, how do you get them back? The way to restore item labels in Windows XP was to repeat the operation and hold the shift key when switching into Thumbnail mode. But wait, Windows Vista doesn't have an explicit Thumbnail mode any more. Since the hold the shift key to hide the labels feature was a rogue feature, nobody knew that the Thumbnail menu item was secretly being overloaded as an escape hatch!

    Okay, here's how you get the labels back: Right-click in the background of the folder and select Customize This folder. From the customization dialog, change the template to Pictures and Videos, then OK. Now go back to the Explorer folder window and right-click in the background of the folder a second time, then go to the View submenu. (Alternatively, type Alt+V.) There will be a new Hide File Names option: Uncheck it. (If it's already unchecked, then check it, and then uncheck it again.) If you want, you can go back and uncustomize the folder so it has the All files template again.

    The customer support people are probably relieved to learn that this rogue feature no longer exists in Windows 7.

  • The Old New Thing

    MS-DOS also allowed spaces in file names, although vanishingly few programs knew how to access them


    A little-known fact about MS-DOS is that it allowed spaces in file names. Sure, you were limited to 8.3, but a file called "LOOK AT.ME" was legal in MS-DOS, and you could indeed create such a file. Good luck finding programs that didn't treat you as insane when you asked for that file, though.

    Although the file system supported files with spaces, practically no programs supported them. Command line tools saw the space as the end of the file name. You couldn't quote the file name because no command line tool supported quotation marks to protect spaces. After all, if you believed that spaces were illegal characters in file names, you wouldn't write extra code to allow people to specify a file name with spaces in them!

    The only program in common use that I remember supporting spaces in file names was GW-BASIC. If you were naive enough to create a file in GW-BASIC with a space in its name, you found yourself in a pretty nasty world of hurt once you escaped GW-BASIC back to the real world. The easiest way to delete such a file was to go back into GW-BASIC and delete it from there.

  • The Old New Thing

    Why was MoveTo replaced with MoveToEx?


    Commenter Ulric asks, "Where did MoveTo(HDC, int, int) go?"

    Back in the 16-bit days, the function to move the current point was called MoveTo, and its return value was a DWORD which encoded the previous position, packing two 16-bit coordinates into a single 32-bit value. As part of the transition to 32-bit Windows, GDI switched to using 32-bit coordinates instead of the wimpy 16-bit coordinates of old. As a result, it was no longer possible to encode the original position in a single DWORD. Something new had to be developed.

    That new thing was the MoveToEx function. Instead of returning a single DWORD, it accepted a final parameter which received the previous coordinates. If you didn't care about the previous coordinates, you could just pass NULL. All of the GDI functions which used to pack two 16-bit coordinates into a single DWORD got Ex-ified in this way so they could accommodate the new 32-bit coordinate system.

    But why did the old MoveTo function go away? Why not keep it around for source code compatibility?

    I find this an interesting question, since most people seem to think that maintaining source code compability between the 32-bit and 64-bit versions of Windows was an idea whose stupidity rivals prosecuting a land war in Asia. (If we had followed this advice, people would just be asking, why did you replace WinExec with the much harder-to-use CreateProcess?) By the same logic, source code compatibility between 16-bit and 32-bit Windows is equally absurd. According to these people, porting 16-bit code to to 32-bit Windows is the best time to introduce these sorts of incompatibilities, in order to force people to rewrite their programs.

    Anyway, the reason we lost MoveTo was that there was no way to return 64 bits of information in a 32-bit integer. Now it's true that in many cases, the caller doesn't actually care about the previous position, but of course the MoveTo function doesn't know that. It returns a value; it doesn't know whether the caller is going to use that return value or not.

    I guess one way out would have been to change the return value of MoveTo to void. That way, people who didn't care about the return value would still compile, while people who did try to use the return value would get a compile error and have to switch to MoveToEx.

    Yeah, I guess that could've been done, but you could also have done that yourself:

    #define MoveTo(hdc, x, y) ((void)MoveToEx(hdc, x, y, NULL))

    I find it interesting that most people who write their own MoveTo macro don't use the (void) cast. In most cases, this is a mistake in porting from 16-bit Windows. (I can tell because the macro is mixed in with a bunch of other porting macros.) However, in other cases, it could be intentional. The authors of the macro may simply not have known about the old 16-bit days and simply expected their macro to be used as if it were prototyped as BOOL MoveTo(HDC, int, int).

    These people will probably be baffled if they run across any actual 16-bit Windows code that tried to extract the high word from the return value of MoveTo. "Why are you extracting the high word from a BOOL?"

    Historical exercise: Instead of adding a new parameter, why not just make MoveToEx return an __int64?

  • The Old New Thing

    Foreign languages can be used to impede communication


    One of the reasons people give for studying a foreign language is to increase the number of people one can communicate with. But what people don't mention is that foreign languages can also be used to impede communications, and that can be just as useful. (Be careful, though, because it can backfire.)

    During my visit to Sweden some years ago, I was walking back to my hotel room from the Göteborg train station. I had spent the afternoon visiting the nearby city of Alingsås, whose claim to fame is that they are the birthplace of the man who introduced potatoes to Sweden, although he is probably more greatly celebrated for introducing a related process to Sweden: the technique of fermenting potatoes to make alcohol. Anyway, the reason I was there was not to learn the history of potatoes in Sweden, but rather to pay a visit to one of my Swedish readers.

    Oh, wait, I was telling a story. I was walking back to my hotel from the train station, and as I crossed one of the plazas, a man approached me, speaking unaccented American English. He said, "Hey, you look Chinese. We have an organization for Chinese people, and the meetings are conducted in Swedish so you can understand!"

    Okay, let's see if we can add up everything wrong with this situation.

    1. We're in Sweden, and I "look Chinese", so he decides to speak to me in English?
    2. He's speaking English in order to convince me to attend a meeting conducted in Swedish.
    3. If I'm Chinese, wouldn't "the language I can understand" be, um, say, some variation of Chinese?

    I didn't feel like pointing this out to the gentleman. I just wanted to get back to my hotel, but he kept following me, repeating his spiel. I stopped and mentally enumerated the languages I knew how to speak.

    • English: Obviously he knows English. He's speaking it.
    • Swedish: We're in Sweden. There's a chance he knows Swedish.
    • German: Göteborg gets a lot of German tourists. The tourism signs and tour buses are trilingual: Swedish, English, and German. So there's a chance he knows German.
    • Chinese: Seeing as he's assuming that I'm a native Chinese speaker, yet he's speaking to me in English, it's a pretty safe bet that he doesn't speak Chinese. Especially if I pick a minority dialect.

    I turned to him and said in my parents' native dialect, "I'm sorry, I don't know what you're saying."

    He was apparently not expecting this, because he paused for a moment before saying "Oh, Thai people are welcome, too." I guess he took what I said and tried to map the phonemes to English and somehow came to the conclusion that I said, "I'm not Chinese; I'm Thai."

    I merely reiterated my claim not to understand what he was saying and continued onward. He decided not to follow me any further.

    I use this technique whenever I don't want to talk to somebody. And the trick works both ways: In Taiwan, when people try to talk to me and I'd rather not deal with them, I speak Swedish.

  • The Old New Thing

    On gender differences in expectations of thinness, and the impact on guys who live in their parents' basement


    At dinner a few years ago, one of my friends brought up a study (which I can't find, so who knows if it's actually true, but let's assume it's true for the sake of the story) that examined the effect of gender differences in expectations of thinness. One of the factors that the study considered was sexual orientation, and they found that homosexual men were, on average, thinner than their heterosexual brethren, and conversely that heterosexual women were thinner on average than their homosexual um, what's the female counterpart to "brethren"?

    In other words, the conclusion of the study was that the pressure to be thin depends not so much on your own gender but rather on the gender of the person you're trying to attract. If you want to attract a man, you are more likely to be thin.

    Like I said, whether what is now a thirdhand report of the study's conclusions is true isn't important to the story. It just served as a catalyst for this snippet of conversation that ensued.

    Deborah: "I can see that. My friend Eleanor [not her real name] is a tall, beautiful Asian woman, and she says she won't date guys unless they have a bit of a pot belly."

    Me: "You do realize that you just instilled hope into the hearts of thousands of guys who live in their parents' basement?"

    Sorry guys, I didn't ask for Eleanor's number.

  • The Old New Thing

    Why does my screen go black when an emergency hibernation is in progress?


    Sometime last year a customer wanted to know why the screen goes black when the system automatically hibernates due to critically low battery power. Shouldn't there be some sort of feedback to tell the user, "Hey, like, I'm hibernating, don't worry"?

    The power management folks explained that they turn off the screen for a reason: They're trying to save your data while they still can. When the system gets the "Oh no, the battery is about to die!" notification from the hardware, there's no time to lose, and even less power to waste. Keeping the screen lit takes a lot of power, so turning it off might make the difference between a successful hibernation and loss of data.

    Mind you, this doesn't all happen without fair warning. Before the battery goes critical, you will get a low battery warning balloon saying "Oh dear, things are getting pretty bad, you really should wrap things up before I'm forced to stop the car!"

    It so happens that this particular customer had a system with a buggy BIOS that fails to notify the operating system of changes in power level with sufficient granularity. The power level went from "okay" straight to "critical" with no steps in between. As a result, Windows doesn't find out about the low battery level until it's already at critically low levels.


    Observe that I wrote "The power management folks explained". I am not the expert here; I'm repeating what I've heard in the interest of getting information out. Unfortunately, it looks like the the Windows Mobile PC Team Blog has gone dark, so it's not clear to me where you can ask your questions. (There is a more general site on Microsoft and the Environment, however.)

Page 1 of 5 (42 items) 12345