June, 2009

  • The Old New Thing

    Oh great, and my phone even has a CPU meter

    • 33 Comments

    These fancy-dancy IP phones never cease to make me wonder what our world has come to. I remember when a telephone was a bucket of carbon granules and a momentary switch, and the rotary dial was just a mechanism for going on and off hook at a precise frequency. (Indeed, sometimes for fun, I'll pulse-dial a phone by tapping on the hook.)

    The other day, somebody sent out an email message:

    I'm amusing myself watching the "CPU Load" graph on the phone. Then again, I'm easily amused.

    Naturally, the CPU meter is useless, because you can only switch to it when you're not using the phone. Once you pick up the handset, the CPU meter dismisses itself so you can see information about the call you're on.

    Oh wait, you can go through the menus to switch back to the CPU meter after it auto-dismisses itself. Woo-hoo, now I can tell people, "Sorry, can you talk slower? My phone's CPU is maxing out."

    This what-barely-qualifies-as-amusement didn't last long. A year later, the units were replaced with a different model phone that didn't have a CPU meter. Progress.

  • The Old New Thing

    High school students guess what happens to money deposited into checking accounts

    • 37 Comments

    In August 2007, the results of the first nationwide high school economics graduation tests were released. (Download the report [pdf].) It appears that the results were better than expected, but let's not celebrate too quickly: The results were that 42% of students rated "Proficient" and 3% "Advanced". And only 52% of the students could answer this multiple-choice question correctly:

    What happens to most of the money deposited in checking accounts at a commercial bank?
    1. It is used to pay the bank's expenses.
    2. It is loaned to other bank customers.
    3. It is kept in the bank's vault until depositors withdraw the funds.
    4. It is paid to owners of the bank as return on their investment.

    I guess 48% of the students have never seen It's a Wonderful Life.

  • The Old New Thing

    Why does a flashing taskbar result in a fullscreen console returning to windowed mode?

    • 23 Comments

    Commenter Daniel wonders why a flashing taskbar results in a fullscreen console returning to windowed mode.

    I didn't know the answer to this, but I formulated a guess, and I was ready to just post my guess. (Because everything I write is just conjecture anyway. Informed conjecture, but still.) But I had some time, so I went spelunking through the code history and about a half hour later, I found confirmation for my guess, so now it's not just a guess but a fact. (Don't expect me to go to all this effort in general. Guessing is a lot less time-consuming.)

    The code to force a fullscreen console into windowed mode when a window flashes was introduced in Windows 2000, and I even found the bug report that led to the change, suitably edited of course:

    Title: A flashing window should ensure that the taskbar (and the window itself?) are both visible
    Date submitted: November 7, 1997

    This is a problem similar to the auto-hide taskbar situation. If the taskbar is not visible, it has to be shown when flashed. This may force a full screen switch.

    If the system is in full screen mode (ie, open a command window and type alt-enter), then if someone calls FlashWindow the user won't see the flashing window. So we have to make the screen switch to windowed mode. This is especially bad when someone calls SetForegroundWindow but we don't let him take the foreground; we simply flash the window instead.

    The bug report pretty much lays out the justification for this change in behavior, so I'll leave it as it is.

  • The Old New Thing

    The butter and the money for the butter

    • 39 Comments

    In a discussion a few years ago, I saw the phrase, "Now you have the butter and the money." This was new to me, and a little Web searching (guided in part by a guess at the author's nationality) revealed it to be a French proverb, the full version of which is On ne peut pas avoir le beurre et l'argent du beurre: "You can't have the butter and the money for the butter." It's a really nice phrase, and maybe someday I'll be able to use it.

    Bonus butter idiom: Reading the blog of a German colleague, I ran across the phrase alles wieder in Butter ("everything back in butter"), which from context appeared to mean something like "everything's all right again." Some more Web searching suggests that I was basically right, and that the idiom comes from the Middle Ages: To prevent glassware transported over the Alps from breaking in transit, a clever businessman discovered that he could set the glasses in a cask, then pour hot butter over them. As the butter cooled, it held the glasses in place, thereby preventing them from rattling against each other and cracking during transport. Everything was back in butter.

  • The Old New Thing

    You can't leave a critical section you never entered

    • 11 Comments

    If you call LeaveCriticalSection on a critical section you never entered, the behavior is undefined.

    Critical sections are an extremly high-traffic code path. Intense work goes into making them as fast as possible. Customers like to ask questions like "Exactly how many cycles does it take to enter a critical section? We're not going to use them if they're too slow." They don't say what they are going to do if critical sections are too slow for them, but the threat is real (even if the justification is bogus). I've seen programmers respond to code feedback of the form "You need a critical section here" with "No, I'm not going to bother. I'm afraid it'll slow down my code."

    Given that critical sections are so heavily used, the algorithm gets tweaked regularly in order to improve performance. Sometimes the tweaks are minor; other times, the algorithm gets a major overhaul. Of course, the hope is that by changing only the insides, nobody will notice. On the other hand, people who relied on undefined behavior (like exiting a critical section they never entered and hoping that something meaningful would happen) are going to see changes in behavior.

    I don't know the precise reasons why the internals of critical sections changed, but I suspect it had to do with mitigating the effect of lock convoy.

  • The Old New Thing

    Don't you hate it when someone leaks a ref to your clothes?

    • 33 Comments

    The other night I had a dream in which one of my friends said, "Check out my clothes closet. This dress is hideous, but I can't get rid of it because there's still a reference to it from my blog." The dresses were labeled 001.jpg through 059.jpg.

  • The Old New Thing

    The dangers of mixing synchronous and asynchronous state

    • 19 Comments

    The window manager distinguishes between synchronous state (the state of the world based on what messages your program has received) and asynchronous state (the actual state of the world this very instant). We saw this earlier when discussing the difference between GetKeyState and GetAsyncKeyState. Here are some other functions and their relationship to the queue state:

    Use synchronous state Use asynchronous state
    GetActiveWindow GetForegroundWindow
    GetMessagePos GetCursorPos
    GetMessageTime GetTickCount

    If you query the asynchronous state while processing a message, you can find yourself caught in a race condition, because the synchronous state of the system when the message was generated may not match the asynchronous state of the system when you receive it. For example, if the users presses a key, and then moves the mouse, calling GetCursorPos from your keypress handler will tell you were the cursor is right now, which is not the same as where the cursor was when the key was pressed.

    Generally speaking, you should use the synchronous state during message handling so that you react to the state of the system at the time the input event took place. Reacting to the asynchronous state of the system introduces race conditions if there is a change to the system state between the time the message was generated and the time the message is processed.

    Of the above functions, GetTickCount is the only one I can think of that has a legitimate usage pattern in common use, namely, when creating timing loops. But if you want to know what time it was when a key was pressed, then GetMessageTime is the function to use.

    This is all a rather length lead-in for my remarks regarding a comment claiming that there is no practical reason why you can't use GetForegroundWindow to determine which window was the one that had focus when a keyboard message was generated. Well, actually, there is, and it's precisely the race condition I've spent most of this article describing. Suppose the user presses a key and then switches to another program. Now your program gets around to processing the keyboard input, and you call GetForegroundWindow, and instead of getting a window from your application, you get some other window from another program. You then pass that window handle to TranslateAccelerator, the keyboard event matches an entry in the accelerator, and boom, you just sent a random WM_COMMAND message to a program that will interpret it to mean something completely different.

    Remember, just because your program has the line

    #define IDC_REFRESH    814
    

    doesn't mean that another program can't have the line

    #define IDC_DELETEALL  814
    

    Now the user presses F5 and switches from your program to that other program. Your program processes the message, queries the asynchronous foreground state with GetForegroundWindow, and gets that other program's window back. You then translate the accelerator, and TranslateAccelerator posts the WM_COMMAND(814) message to that other program, which interprets it as "delete all".

    The great thing about this is that the users will probably blame the other program. "Sometimes, when I use this program, it spontaneously deletes all my items. Stupid program. It's so buggy."

    Commenter poenits correctly points out that I failed to take into account the case where the message is posted directly to the dialog. (The dialog manager tries not to put keyboard focus on the dialog itself, but if you play weird games, you can find yourself backed into that situation, such as if you delete all the controls on a dialog!) The fix, however, is not to translate the message directly to the window with keyboard focus, because the window with keyboard focus might belong to a third dialog that you don't want to translate accelerators for. (That other window might have used the other header file which defines message 814 to be IDC_DELETEALL.) Just check for your specific window directly:

    if (hwnd1== msg.hwnd || IsChild(hwnd1, msg.hwnd))
        TranslateAccelerator(hwnd1, hAccel, &msg);
    else if (hwnd2 == msg.hwnd || IsChild(hwnd2, msg.hwnd))
        TranslateAccelerator(hwnd2, hAccel, &msg);
    

    Think of TranslateAccelerator as MaybePostWM_COMMAND. The first parameter to TranslateAccelerator must be a window you are certain knows how to interpret the WM_COMMAND message that you might end up posting. You know which windows understand your custom WM_COMMAND messages. Pass one of those known windows, not some random unknown window that you calculated from unknown sources.

    Passing an unknown window as the first parameter to TranslateAccelerator is like falling for one of those phishing scams. If you get a random piece of email telling you "Hey, call this number and give me your personal information," you're not going to do it. If you really want to contact your bank, you ignore the phone number in the email and just call the number you know and trust to be your bank's service desk. Similarly, you shouldn't be posting your personal messages to some random window you receive. Post it to the known trusted window. Otherwise you're just sending your money to some unknown recipient in Nigeria.

  • The Old New Thing

    Welcome to Leavenworth, Washington's faux-Bavarian village

    • 19 Comments

    The dying logging town of Leavenworth, Washington reinvented itself in the 1960's as a faux-Bavarian village. Today, over a million tourists visit annually to enjoy the scenic mountain views, soak in the fake Bavarian atmosphere, and revel in events like the Leavenworth International Accordion Celebration which starts tomorrow, or the three-weekend-long Leavenworth Oktoberfest every October. (Mind you, the Leavenworth Oktoberfest doesn't actually start until the Munich Oktoberfest is nearly over, because Oktoberfest starts in September.)

    I found during a brief visit to Leavenworth that the people there may dress like they're from Bavaria, but they don't actually speak German.

    But at least I was there undercover.

    Some years ago, a colleague of mine was on assignment in Redmond from his home country of Austria. One weekend, he decided to pay a visit to our fake Bavarian village, and when he returned, we asked him what he thought of the town.

    "Well, for a fake Bavarian village, it's not too bad. I mean, nobody would for a moment think it was the real thing, but I appreciate the effort they went to, and it was quite a pleasant little town. But the weird thing was what happened whenever I opened my mouth to speak: People recognized that I spoke with a German accent and a flash of panic crossed their faces, as if I was going to blow the cover off their little ruse and reveal it to be a fraud."

    [Update 8:00AM: Various typos fixed.]

  • The Old New Thing

    Sure, I can get spurious WM_MOUSEMOVE messages, but why do they keep streaming in?

    • 20 Comments

    I wrote some time ago that the window manager generates spurious WM_MOUSEMOVE messages in order to let programs know that the mouse has entered the window even if the reason was a window hierarchy reshuffle rather than a physical motion of the pointing device. But some people have noticed that that explanation fails to account for all the WM_MOUSEMOVE messages that are being delivered. In particular, the reasoning fails to explain why a stream of WM_MOUSEMOVE messages is being generated. So where is this infinite stream of WM_MOUSEMOVE messages coming from, even when the window hierarchy is stable?

    They're most likely coming from some third party so-called enhancement software.

    The Windows performance and mobility teams keep a close eye on these sort of continuous phenomena. The performance folks are interested because this continuous stream of messages suck away resources that could be used for something more productive. It's not just the cost in CPU. The memory in the message handling code path can't be paged out since it's being hit all the time. The context switches force CPU caches to be flushed. Algorithms which had been tuned to reside entirely within the L2 cache now find themselves going out to slower main memory. Meanwhile, the mobility team is concerned because all this continuous activity runs down your battery, prevents the CPU from going into a low-power state, and prevents your screen saver from kicking in.

    If you find a continuous stream of WM_MOUSEMOVE messages, then there is some continuous activity going on that is causing it. It might be some software that is polling the mouse in order to provide "extra value". For example, they might check the mouse cursor position and try to guess what it is positioned over, but they never realize that "You know, if nothing has changed, the answer is probably the same as it as last time you checked." Or, as the author of linked posting above eventually figured out, it might be a buggy wireless mouse which not only is sucking down your CPU and preventing your screen saver from running, but is also draining your wireless mouse battery!

  • The Old New Thing

    Management-speak: Upping the sats and stimulating the ecosystem

    • 37 Comments

    Here's another sentence that's so loaded with buzzwords and buzzphrases I'm not sure what language it's written in.

    I just want to have creative control over how my audience can interact with me without resorting to complex hacking in a way that is easy to explain but ups our blogging audiences sats to a new level that may also stimulate a developer ecosytem that breeds quality innovation...

    The ellipses are in the original, if that helps any.

    The scary thing is: The person who wrote this isn't even a manager.

Page 2 of 5 (41 items) 12345