• The Old New Thing

    Dinner at the Herbfarm in Woodinville


    As part of the going-away festivities for my friend, a group of us went to The Herbfarm, the local restaurant referenced in Clue I of Puzzle #3.

    The restaurant is nestled in the Sammamish Valley, right next to the Willows Lodge resort and its restaurant, The Barking Frog. Less than a kilometer down the road is the Chateau Ste. Michelle Winery. All the high-falutin' wine-snob destinations in one convenient location. (Right behind is the Redhook Brewery, if you tire of the whole urbane ambience and just want a beer and a sandwich.)

    Actually, the word "restaurant" doesn't do the Herbfarm justice. It's really a "total dining experience". The evening begins at 4pm with a tour of the herb garden. After heading inside, you are introduced to the evening's menu and the restaurant staff. (This restaurant has a staff mushroom forager!) Once the introductions are complete, the nine-course five-hour meal begins.

    For posterity, I record the menu below.

    A Fete for the Sun
    The Herbfarm • Sunday, July 24, 2005

    From the Water's Edge
    Paddlefish Caviar on Cucumber Gelée
    Westcott Bay Mussel Skewer
    Razor Clams with Sea Beans
    1999 Argyle Oregon Brut

    Spice-Crusted Pacific Albacore
    On a Salad of Beets, Wasabi, and Dill
    2003 Rulo Winery Viognier, Walla Walla

    Dungeness Crab, Chanterelle, & Lamb's Quarter Lasagna
    2004 Dr. Loosen/Chateau Ste. Michelle “Eroica” Riesling

    Troll-Caught Sockeye Salmon
    Slow Roasted in Squash Blossoms
    With Zucchini Strands and Sorrel-Lemon Thyme Sauce
    2004 Chinook Wines Rosé of Cabernet Franc

    Tarragon Ice & Apricot Float

    Three Tastes of Muscovy Duck
    Lavender-Crusted Breast on Onion Pudding
    With Black Currant Sauce
    Duck Confit with Just-Dug Potatoes
    Slow-Braised Leg on Morel Risotto
    2002 Cougar Crest Reserve Syrah, Stellar Vineyard

    An Herbfarm Garden Salad
    With Currants & Sally Jackson Guernsey Cow Cheese

    Sonata of Summer Desserts
    Anise Hyssop Panna Cotta with Raspberries
    Marionberry-Rose Geranium Ice Cream Cone
    Almond-Filled Donut Peach with Lemon Verbena Yogurt Ice Cream

    Brewed Coffees, Teas & Infusions

    A Selection of Small Treats
    Vintage 1916 Barbeito Malvazia Madeira

    Multigrain Rolls & Herbed Foccacia

    Between the duck and salad courses, we stepped outside to feed the pigs.

    The preliminary tour of the herb garden primed me to appreciate the extensive range of herbs employed in the various dishes. (We also learned herb trivia—daylilies are edible, as are zucchini and chive blossoms. I found this part most fascinating, learning about herbs and how the various elements were chosen for the dishes to come.) The garden salad, it seemed, didn't have two leaves from the same plant!

    If you're considering paying the Herbfarm a visit, be warned: You need to make reservations months in advance, and the evening will set you back a pretty penny.

    And we did pay the bill before we left.

  • The Old New Thing

    On paying for your meal upon leaving a restaurant


    Robert Scoble's embarrassment over forgetting to pay a restaurant bill reminds me of an even more embarrassing incident experienced by a component team from the Windows 95 team.

    To celebrate something or other, their team went to lunch at The Salish Lodge, a fine dining establishment. At the end of the meal, everybody thought somebody else was going to handle the bill, and they all walked out as a group. The administrative assistant who made the reservation received a somewhat concerned telephone call from the restaurant when they discovered that a large party just skipped the check. Profuse apologies were extended and the bill was settled over the phone (with what I assume was a very generous tip). I just happened to be in the hallway when this whole thing happened and got to hear the story from the very exasperated administrative assistant shortly after it transpired.

    So remember, folks: Pay the bill before leaving the restaurant. It saves everybody a lot of grief.

  • The Old New Thing

    Marin Alsop to be music director of the Baltimore Symphony Orchestra


    Marin Alsop has been selected to lead the Baltimore Symphony Orchestra. The development has gotten a lot of attention, presumably, because this makes Maestra Alsop (as she prefers to be called) the first woman to be named music director of a major U.S. orchestra. I saw her perform in Seattle earlier this year and thought she did a fine job. If I'd known she'd become a big newsmaker a few months later, I would have taken notes!

    The focus on her "breakthrough accomplishment" just strikes me as odd. I thought we as a society were beyond being concerned about the gender of the best person for the job. I remember somebody asking, "What it like being from the first state in the United States to have your governor and both senators all women?" It never even occurred to me that all three positions were held by women. It struck me as silly as the question, "What it like being from the first state in the United States to have your governor and both senators all have blonde hair?" What kind of answer were they looking for?

    (Curiously, if you ask Google Who is the governor of Washington?, it says the answer is Gary Locke. Don't use Google to cheat on your civics exam yet.)

  • The Old New Thing

    The importance of passing the WT_EXECUTELONGFUNCTION flag to QueueUserWorkItem


    One of the flags to the QueueUserWorkItem function is WT_EXECUTELONGFUNCTION. The documentation for that flag reads

    The callback function can perform a long wait. This flag helps the system to decide if it should create a new thread.

    As noted in the documentation, the thread pool uses this flag to decide whether it should create a new thread or wait for an existing work item to finish. If all the current thread pool threads are busy running work items and there is another work item to dispatch, it will tend to wait for one of the existing work items to complete if they are "short", because the expectation is that some work item will finish quickly and its thread will become available to run a new work item. On the other hand, if the work items are marked WT_EXECUTELONGFUNCTION, then the thread pool knows that waiting for the running work item to complete is not going to be very productive, so it is more likely to create a new thread.

    If you fail to mark a long work item with the WT_EXECUTELONGFUNCTION flag, then the thread pool ends up waiting for that work item to complete, when it really should be kicking off a new thread. Eventually, the thread pool gets impatient and figures out that you lied to it, and it creates a new thread anyway. But it often takes a while before the thread pool realizes that it's been waiting in vain.

    Let's illustrate this with a simple console program.

    #include <windows.h>
    #include <stdio.h>
    DWORD g_dwLastTick;
    void CALLBACK Tick(void *, BOOLEAN)
     DWORD dwTick = GetTickCount();
     printf("%5d\n", dwTick - g_dwLastTick);
    DWORD CALLBACK Clog(void *)
     return 0;
    int __cdecl
    main(int argc, char* argv[])
     g_dwLastTick = GetTickCount();
     switch (argc) {
     case 2: QueueUserWorkItem(Clog, NULL, 0); break;
     case 3: QueueUserWorkItem(Clog, NULL, WT_EXECUTELONGFUNCTION); break;
     HANDLE hTimer;
     CreateTimerQueueTimer(&hTimer, NULL, Tick, NULL, 250, 250, 0);
     return 0;

    This program creates a periodic thread pool work item that fires every 250ms, and which merely prints how much time has elapsed since the timer was started. As a baseline, run the program with no parameters, and observe that the callbacks occur at roughly 250ms intervals, as expected.


    Next, run the program with a single command line parameter. This causes the "case 2" to be taken, where the "Clog" work item is queued. The "Clog" does what its names does: It clogs up the work item queue by taking a long time (four seconds) to complete. Notice that the first callback doesn't occur for a whole second.


    That's because we queued the "Clog" work item without the WT_EXECUTELONGFUNCTION flag. In other words, we told the thread pool, "Oh, don't worry about this guy, he'll be finished soon." The thread pool wanted to run the Tick event, and since the Clog work item was marked as "fast", the thread pool decided to wait for it and recycle its thread rather than create a new one. After about a second, the thread pool got impatient and spun up a new thread to service the now-long-overdue Tick events.

    Notice that as soon as the first Tick event was processed, three more were fired in rapid succession. That's because the thread pool realized that it had fallen four events behind (thanks to the clog) and had to fire the next three immediately just to clear its backlog. The fifth and subsequent events fire roughly on time because the thread pool has figured out that the Clog really is a clog and should be treated as a long-running event.

    Finally, run the program with two command line parameters. This causes the "case 3" to be taken, where we queue up the Clog but also pass the WT_EXECUTELONGFUNCTION flag.


    Notice that with this hint, the thread pool no longer gets fooled by the Clog and knows to spin up a new thread to handle the Tick events.

    Moral of the story: If you're going to go wading into the thread pool, make sure you play friendly with other kids and let the thread pool know ahead of time whether you're going to take a long time. This allows the thread pool to keep the number of worker threads low (thus reaping the benefits of thread pooling) while still creating enough threads to keep the events flowing smoothly.

    Exercise: What are the consequences to the thread pool if you create a thread pool timer whose callback takes longer to complete than its timer period?

  • The Old New Thing

    News flash: Going for a walk on a nice day makes you feel better


    Scientists continue to amaze us with their research breakthroughs, such as a discovery late last year that going for a walk on a nice day makes you feel better. What would we do without science?

  • The Old New Thing

    FindFirstFile is not a SQL query


    The FindFirstFile function is not a SQL query. It's a very simple directory enumerator. There is a slightly fancier version called FindFirstFileEx, but even that function doesn't add much at present beyond filtering for directories or devices.

    You don't get to pass it sort criteria like or "return the files/directories sorted smallest file first", or "return the files/directories in reverse order of creation" The only filtering you can provide are the wildcard pattern and (if you use FindFirstFileEx) a directory filter. The wildcard language is very limited as well; it can't express queries like "files whose extension are either .exe or .dll" or "all files whose extension is .c plus all directories regardless of extension". You also can't ask it questions like, "Tell me the total size of the files in this directory", for as we saw earlier, this question is underspecified.

    If you want to do any of those advanced queries, you'll have to code it up yourself. Or as Hippie Tim is fond of saying, "Start typing!"

  • The Old New Thing

    The Northwest Mahler Festival performs Mahler's Second Symphony ("Resurrection")


    Last night I attended the Northwest Mahler Festival's performance of Mahler's Second Symphony (The Resurrection). The concert opened with Copland's El Salón México and Barber's Prayers of Kierkegaard. [Typo fixed 12:30pm]

    The Copland was kind of shaky, in a way that I couldn't quite put a finger on. The wind balance seemed a bit off, and it somehow didn't seem to "come together". By contrast, my knowledge of the Barber was zero, so they could've pulled out kazoos and I wouldn't've know that something was amiss.

    The Mahler demands quite a bit from both the woodwind and brass sections, but I was relieved to find that the tricky problem of getting them to play friendly appeared to be nonexistent. The Mahler "came together". (Well, duh, this is the Northwest Mahler Festival, after all.) I was so at ease with it that I started to ignore the occasional technical error...

    Performances of Mahler symphonies have a significant visual component. It's always a blast to see the clarinets playing "Schalltrichter auf", and for the Second, I was oddly fascinated by the rute. (I think my favorite Mahler percussion instrument is the "large hammer striking a wooden block" from the Sixth Symphony. When you see the percussionist raise that huge mallet, you know it's coming... and when the blow finally comes, it sends shock waves through your body.)

    Anyway, there's no real point to this entry. Just babbling about a symphony concert that I found very satisfying.

  • The Old New Thing

    Why does FindFirstFile find short names?


    The FindFirstFile function matches both the short and long names. This can produce somewhat surprising results. For example, if you ask for "*.htm", this also gives you the file "x.html" since its short name is "X~1.HTM".

    Why does it bother matching short names? Shouldn't it match only long names? After all, only old 16-bit programs use short names.

    But that's the problem: 16-bit programs use short names.

    Through a process known as generic thunks, a 16-bit program can load a 32-bit DLL and call into it. Windows 95 and the Windows 16-bit emulation layer in Windows NT rely heavily on generic thunks so that they don't have to write two versions of everything. Instead, the 16-bit version just thunks up to the 32-bit version.

    Note, however, that this would mean that 32-bit DLLs would see two different views of the file system, depending on whether they are hosted from a 16-bit process or a 32-bit process.

    "Then make the FindFirstFile function check to see who its caller is and change its behavior accordingly," doesn't fly because you can't trust the return address.

    Even if this problem were solved, you would still have the problem of 16/32 interop across the process boundary.

    For example, suppose a 16-bit program calls WinExec("notepad X~1.HTM"). The 32-bit Notepad program had better open the file X~1.HTM even though it's a short name. What's more, a common way to get properties of a file such as its last access time is to call FindFirstFile with the file name, since the WIN32_FIND_DATA structure returns that information as part of the find data. (Note: GetFileAttributesEx is a better choice, but that function is comparatively new.) If the FindFirstFile function did not work for short file names, then the above trick would fail for short names passed across the 16/32 boundary.

    As another example, suppose the DLL saves the file name in a location external to the process, say a configuration file, the registry, or a shared memory block. If a 16-bit program program calls into this DLL, it would pass short names, whereas if a 32-bit program calls into the DLL, it would pass long names. If the file system functions returned only long names for 32-bit programs, then the copy of the DLL running in a 32-bit program would not be able to read the data written by the DLL running in a 16-bit program.

  • The Old New Thing

    What is the deal with the ES_OEMCONVERT flag?


    The ES_OEMCONVERT edit control style is a holdover from 16-bit Windows. This ancient MSDN article from the Windows 3.1 SDK describes the flag thus:

    ES_OEMCONVERT causes text entered into the edit control to be converted from ANSI to OEM and then back to ANSI. This ensures proper character conversion when the application calls the AnsiToOem function to convert a Windows string in the edit control to OEM characters. ES_OEMCONVERT is most useful for edit controls that contain filenames.

    Set the wayback machine to, well, January 31, 1992, the date of the article.

    At this time, the predominant Windows platform was Windows 3.0. Windows 3.1 was still a few months away from release, and Windows NT 3.1 was over a year away. The predominant file system was 16-bit FAT, and the relevant feature of FAT of this era for the purpose of this discussion is that file names were stored on disk in the OEM character set. (We discussed the history behind the schism between the OEM and ANSI code pages in an earlier article.)

    Since GUI programs used the ANSI character set, but file names were stored in the OEM character set, the only characters that could be used in file names from GUI programs were those that exist in both character sets. If a character existed in the ANSI character set but not the OEM character set, then there would be no way of using it as a file name; and if a character existed in the OEM character set but not the ANSI character set, the GUI program couldn't manipulate it.

    The ES_OEMCONVERT flag on a edit control ensures that only characters that exist in both the ANSI and OEM character sets are used, hence the remark "ES_OEMCONVERT is most useful for edit controls that contain filenames".

    Fast-forward to today.

    All the popular Windows file systems support Unicode file names and have for ten years. There is no longer a data loss converting from the ANSI character set to the character set used by the file system. Therefore, there is no need to filter out any characters to forestall the user typing a character that will be lost during the conversion to a file name. In other words, the ES_OEMCONVERT flag is pointless today. It's a leftover from the days before Unicode.

    Indeed, if you use this flag, you make your program worse, not better, because it unnecessarily restricts the set of characters that the user will be allowed to use in file names. A user running the US-English version of Windows would not be allowed to enter Chinese characters as a file name, for example, even though the file system is perfectly capable of creating files whose names contain those characters.

  • The Old New Thing

    Watching the game of "Telephone" play out on the Internet


    Let's see if I can get this straight.

    First, Chris Pirillo says (timecode 37:59) he's not entirely pleased with the word "podcast" in Episode 11 of This Week in Tech. The Seattle-PI then reports that the sentiment is shared with "several Microsoft employees" who have coined the word "blogcast" to replace it. Next, c|net picks up the story and says that the word "podcast" is a "faux-pas" on Microsoft campus. [Typo fixed: 9am]

    In this manner, a remark by someone who isn't even a Microsoft employee becomes, through rumor, speculation, and wild extrapolation, a word-ban at Microsoft.

    Pretty neat trick.

Page 373 of 455 (4,543 items) «371372373374375»