July, 2009

  • The Old New Thing

    Why was MoveTo replaced with MoveToEx?

    • 42 Comments

    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

    Film students and The Bicycle Thief

    • 41 Comments

    The current generation of young people grew up in a very different world from us older folks. There has always been an Internet. Everybody is accessible by mobile phone. Cars have always had power windows. (Which reminds me of a story of a friend of mine who has an older-model car and was giving a ride to an eight-year-old relative. The youngster pointed at the window crank and asked, "What's this?" Upon learning its purpose, the young passenger spent the remainder of the trip opening and closing the window, giggling with glee. "You know, most people pay extra so they don't have to do that.")

    But it's not just elementary school children whose views of the world are different.

    Some time ago, I was at a dinner where another guest was a film professor at the local university. In one class, they were discussing the classic movie Ladri di Biciclette (The Bicycle Thief in the United States), the story of a poor man in post-war Italy searching for his stolen bicycle, the bicycle he needs for his job. One student asked, "Why doesn't he just buy another bicycle?"

  • The Old New Thing

    What happens to your restaurant tip?

    • 37 Comments

    Some time ago, the Seattle Times ran an article on how your restaurant tip gets divided up among the staff. A week later, they ran an entire article of responses to the original article, some from customers, but many from restaurant staff (both cooks and servers). And, now on a roll, the next week's food section looked at the sociology of splitting the bill with a sidebar looking at how hard it is for different types of restaurants.

  • The Old New Thing

    The advantage of knowing your limits of discrimination

    • 37 Comments

    A story a while back about ridiculously expensive speaker cables and James Randi's challenge to tell the difference between them and modestly-priced cables reminded me of a conversation I had with a wine-loving friend of mine.

    He went on a wine tasting tour and sampled wines of varying quality and price. His conclusion was that he could detect the correlation between price and quality up until about $75/bottle. Beyond that point, the wines all tasted roughly equally great.

    Conclusion: There's no point in my friend spending more than about $75 on a bottle of wine. Once you know the limit of your discrimination, you can use it to avoid wasting money. (One might argue that this is one advantage of having a coarse palate: You can get away with cheaper wine!)

    Related: Commenter Eff Five notes that researchers have determined that people perceive the same wine as tasting better if they are told that it is more expensive.

  • The Old New Thing

    Speculation on how a mishandled 13-character string can result in a blue screen

    • 35 Comments

    Commenter nolan reminisces about an old Windows 95 bug in the networking layer that crashed if a string was exactly 13 characters long. "So for the past 10 years or so, I've been wondering exactly how one could write code with that bug. Any bug that weird has to have a great story behind it."

    I don't know what the story behind it is, but if after ten years you still can't imagine how such a bug could be possible, you don't have a very active imagination.

    SomeFunction(char *hostname)
    {
     char tmpbuffer[13]; // most host names are less than this size
     char *buffer;
     if (strlen(hostname) > sizeof(tmpbuffer)) {
       buffer = strdup(hostname);
       if (!buffer) return some error;
     } else {
       buffer = strcpy(tmpbuffer, hostname);
     }
     ... do stuff with buffer ...
     if (buffer != tmpbuffer) free(buffer);
    }
    

    If the host name is exactly 13 characters, then this code overflows the buffer by one character, corrupting the stack. A crash is hardly surprising at this point.

  • The Old New Thing

    Proto-Microspeak: Coceptualize

    • 35 Comments

    Many years ago, to see whether anybody was paying attention, a colleague and I slipped the made-up word "coceptualize" into a document.

    Nobody said a thing.

    Either nobody read that part of the document, or they did and thought it was a real word.

  • The Old New Thing

    Polling by sleeping versus polling by waiting with a timeout

    • 34 Comments

    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 ..
     Sleep(50);
    }
    
    // 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

    Command line parsers look at what you typed, not what what you typed looks like

    • 32 Comments

    Command line parsers are stricter than human beings. The computer cares about what you typed. If you type something else that superficially resembles what you want, but is not actually what you want, then you won't get what you want, even though it sure looks like what you want.

    I covered a special case of this topic earlier when I described smart quotes as the hidden scourge of text meant for computer consumption. You think you typed a quotation mark, but the editor secretly "improves" it from U+0022 to U+201C. Then you paste the text into a command line and you get strange output because the command line parser uses U+0022 as the quotation mark, not characters like U+201C which physically resemble U+0022 but aren't. A human being would say, "Yeah, that's a quotation mark, we'll let it slide." A command line parser knows what it wants and accepts no substitutes.

    Even though my original examples are for command line use, the principle applies elsewhere, and I'm going to use CSS selectors as my example, because the command line programs used in my original examples are internal Microsoft tools, and explaining their command line syntax would distract from the message. On the other hand, everybody can look up CSS selector syntax. (There is an opportunity for a snarky comment here, but I'm going to withhold the pre-emptive snarky comment in the hopes that my readers are mature enough to not go for the cheap drive-by insult. I am almost always disappointed by the result, but I try again every so often to see if the environment has changed.)

    Here is an imaginary question/answer session inspired by actual events:

    From: Xxxx Xxxxx

    How do I make a CSS rule apply only to elements with a specific tag and a specific class? Specifically, I want a rule to apply only to elements of the form <SPAN CLASS="Name">.

    From: Yyyyy Yyyyyy

    You use SPAN.Name.

    From: Xxxx Xxxxx

    I tried that, but it doesn't work.

    SPAN. Name { color: red; }
    

    This person became one of those people who are not interested in why something works but are only interested in the magic phrase they need to type. Whether or not you believe that the "just tell me what to type" mindset is acceptable, you have to concede that if you choose to adopt that mindset, you need to actually type what people tell you to type.

    In this case, the person decided that the punctuation rules for CSS are the same as the punctuation rules for English, and since English allows (and even encourages) a space after a period, then CSS should also allow it. "I mean, it looks so much better on the screen with a space after the period." (I bet these are the same people who move cities around on a map in order to produce a more visually-pleasing arrangement.)

    Or maybe the person decided that the punctuation rules for CSS were the same as C++. C++ allows spaces on either side of the field selector operator. If C++ allows it, then so too should CSS.

    Of course, neither case is true. CSS has its own rules for parsing, and in CSS, spaces are significant.

    What I found even more mind-boggling was another question/answer session. I'm going to use the same question and answer for illustrative purposes, but in reality, the question was different.

    From: Wwww Wwwww

    How do I make a CSS rule apply only to elements with a specific tag and a specific class? Specifically, I want a rule to apply only to elements of the form <SPAN CLASS="Name">.

    From: Yyyyy Yyyyyy

    You use SPAN.Name.

    From: Wwww Wwwww

    I tried that, but it doesn't work.

    .Name SPAN { color: red; }
    

    I don't know what possessed this second person to take the instructions and then scramble the pieces on the assumption that, hey, the order of the pieces of the selector aren't important, as long as they're all there, right?

  • The Old New Thing

    How do I quickly position two windows side by side?

    • 31 Comments

    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

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

    • 30 Comments

    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.

Page 1 of 5 (42 items) 12345