Holy cow, I wrote a book!
Oscar Night is a few weeks away, but
when you settle in to watch the show with your bowl of popcorn,
please be aware that inhaling deeply from the
fumes of a freshly-opened bag of microwave popcorn is
not the greatest decision you can make from a health standpoint.
(Then again, you probably ought to reconsider
eating microwave popcorn in the first place,
but let's leave that aside.)
A disease informally known as popcorn lung afflicts
people who work in popcorn factories and has been known since 2002.
But in 2007,
doctor diagnosed the first case of popcorn lung in an end-user.
The risk is not from eating the popcorn but from breathing it.
"This patient described enjoying the smell so much he was
actually inhaling the steam."
The best part of the article was when the patient was asked,
"Are you around a lot of popcorn?"
"I am popcorn."
Update: Oscar Night is
not actually this weekend.
That's what happens when you schedule your blog entries over a year
in advance and have to guess when Oscar Night is coming.
We saw fibers a long time ago when I looked at how you can
use fibers as a form of coroutines to simplify the writing of
A fiber is a handy tool,
but it's a tool with very sharp edges.
fibers are promiscuous with threads,
you have to be careful when running code that cares
about what thread it is running on,
because that code may discover that its thread
changed out from under it.
For example, critical sections and mutexes remember which thread
If you enter a critical section on a fiber,
and then you unschedule the fiber,
then reschedule it onto a different thread,
and then you leave the critical section,
your critical section will end up corrupted because
you broke the rule that says that a critical section
must be exited on the same thread that entered it.
Actually, you were already in bad shape once you unscheduled
the fiber while it owned a resource:
An unscheduled fiber cannot release the resource.
Unscheduling a fiber is like
suspending a thread:
Anybody who later waits for that fiber to do anything will be
waiting for an awful long time,
because the fiber isn't running at all.
The difference, though, is that the fiber is unscheduled at controlled
points in its execution, so you at least have a chance at suspending
it at a safe time if you understand what the fiber is doing.
For example, suppose you enter a critical section on a fiber,
and then unschedule the fiber.
Some time later, a thread (either running as a plain thread
or a thread which is hosting a fiber)
tries to enter the critical section.
One of two things can happen:
if you use an object which has thread affinity on a fiber,
you are pretty much committed to keeping that fiber on that
thread until the affinity is broken.
This affinity can be subtle,
because most code was not written with fibers in mind.
Any code which calls TlsGetValue has thread
because thread local storage is a per-thread value,
not a per-fiber value.
(This also applies to moral equivalents to TlsGetValue,
like code which calls GetCurrentThreadId and uses it as
a lookup key in a table.)
You need to use FlsGetValue to get values
which follow fibers around.
But on the other hand, if the code is not running on a fiber,
then you can't call FlsGetValue since there is no
fiber to retrieve the value from.
This dichotomy means that it's very hard if not impossible
to write code that is both thread-safe and fiber-aware
if it needs to store data externally on a per-thread/fiber basis.
Even if you manage to detect whether you are running on a thread or
a fiber and call the appropriate function,
if somebody calls ConvertThreadToFiber or
then the correct location for storing your data changed
behind your back.
If you are calling into code that you do not yourself control,
then in the absence of documentation to the contrary,
you don't really have enough information to know whether
the function is safe to call on a fiber.
For example, C runtime functions like
have thread affinity (even though there's nothing obviously
threadlike about comparing strings)
because they rely on the current thread's locale.
(similar to the bottom line from
You have to understand the code that runs on your fiber,
or you may end up accidentally stabbing yourself in the eyeball.
Structured exception handling is fiber-safe since it
is stack-based rather than thread-based.
Note, however, that when you call ConvertThreadToFiber,
any active structured exception handling frames on the thread
become part of the fiber.
Wow, it's been a long time since
my last rant against food products that are offenses against nature.
Today's rant is against
a product which
Kraft launched in April 2008.
Bagel-fuls (note the hyphen and the lowercase "f")
are a dense, doughy material formed into a log shape,
with a cream cheese filling.
Think of them as
but with cream cheese instead of a sugar
cream filling, and with a dense, doughy substance instead of
whatever alien material it is they make Twinkies out of.
The great thing about this product is that it is an attempt
by Kraft to learn its lesson from a previous failed bagel-like product:
Philadelphia To Go bagel,
a package consisting of a frozen bagel,
a one-ounce tub of cream cheese, and a plastic knife.
For people who are unable to remember where they kept their
cream cheese (hint: the refrigerator) and knives (hint: cutlery drawer).
Apparently, Kraft's conclusion was not that the product failed
because it was too stupid, but rather that it failed because
it was not stupid enough.
What happens to the fibers which ran on a thread when the thread exits?
Are all the fibers destroyed?
No, only the currently-executing fiber is destroyed.
Fibers running on other threads and fibers which are not
running on any thread at all are not affected.
Fibers do not have thread affinity (when not running),
and they do not remember what threads they have been run on.
Indeed, one of the features of fibers is that you can switch away
from a fiber on one thread,
then switch to that same fiber on another thread,
and that fiber will resume execution on the new thread.
Fibers are the social butterflies of scheduling:
They will hang out on any thread that invites them to run.
Once one thread deschedules a fiber,
the fiber loses any affinity for the thread and is perfectly
happy to hang out on any other thread.
Or on the original thread,
if the original thread comes crawling back begging for another chance.
You can run a fiber on any thread you want,
provided you don't run it on two threads at once.
(Well, and of course, you have to have prepared the thread for
fiber execution by calling ConvertThreadToFiber.)
Next time, some additional musing about fibers.
Be careful not to
confuse the two.
Since we're sharing:
During a conversation in German, I talked about
seeing Unfall (accident) instead of Abfall
(garbage) on the street.
To my credit, I immediately corrected my error.
To my discredit, the error was made at the state finals of
a German language contest.
Some time ago,
asked (and answered),
How the @#%&*! does CBS_SORT choose to sort it all out?
One detail in his answer is that the sorting algorithm used
is basically CompareString,
with special treatment for the left square bracket U+005B.
Why is the left square bracket so special?
It goes back to the LB_DIR message
(which is in turn used by
and related functions).
If you ask for drives to be added to the list or combo box,
they are added in the form [-X-], where X
is the drive letter.
The left square bracket is special-cased so that the drive
letters sort to the top of the list.
Of course, LB_DIR and related functions and messages
are pretty old-school nowadays,
but the code for them is still around,
so the sort function still needs to worry about them.
As I noted some time ago,
one of the most important lessons I learned from Systemantics
is Le Chatelier's Principle for complex systems
"Every complex system resists its proper functioning."
At Microsoft, there are processes galore.
For example, when a server is taken down for planned maintenance,
you can expect a series of messages, perhaps following this pattern:
The problem with this is that you often receive notifications
for servers you have no interest in,
indeed whose mere existence you were previously entirely unaware of.
The notification messages don't include instructions on how
to stop receiving the notifications,
or if they do, the instructions are incorrect
(no points for guessing how I discovered this),
so people set up email rules to auto-delete the notifications
instead of trying to figure out how to unsubscribe.
The result is that we now have a system in place which generates
large quantities of email which are automatically deleted.
Michael Agger expounds on
increasing pressure for people to provide pictures of themselves online.
I've managed to resist so far.
That article also tipped me off to a phenomenon I didn't even know
had a name:
"What's the proper way to add keyboard support to a dialog box?"
There are many options available to you.
The most traditional way is to
pick them off in the dialog loop,
either hard-coding the keys in code
or putting them into resources by
moving them to an accelerator resource.
Moving them to an accelerator resource is a good idea if the keys
are subject to translation (for example, if they are mnemonic).
On the other hand, picking them off in code is your only choice
if the action you want to take cannot be mapped to a WM_COMMAND
message (or if you simply don't feel like creating such a mapping).
SuperBK appears to be using MFC,
a framework I have only cursory familiarity with,
so I'll accept that the MFC way of customizing the dialog loop
is to use PreTranslateMessage.
One issue that was raised was the case where a keyboard accelerator
is active only when a certain window has keyboard focus.
But if that's your design,
then you don't need to mess with the dialog loop at all.
For example, the space bar pushes a button,
but only if focus is on the button.
There is no special code in the dialog loop to accomplish this;
it's just part of the button control's
WM_KEYDOWN message handler.
This is one of those cases where you discovered a hammer and
start seeing everything as a nail.
When the user presses a key,
the keyboard message is posted to the window that has keyboard focus.
You don't have to do any special work to pick it off,
because it'll get to that window anyway if you just leave it alone.
In SuperBK's specific example, the list box should behave a certain
way if it has focus and the user hits VK_RETURN.
Okay, well, VK_RETURN is a special keyboard navigation
key for dialog boxes, so you need to tell the dialog manager,
"No, I want this key to go to me."
Just have the control return
DLGC_WANTMESSAGE in response to
WM_GETDLGCODE if the message is a press of the
The dialog manager will let the message go through to the window,
and then the window can perform its custom VK_RETURN
I was in the grocery store,
and there was a sign advertising a new product.
Delight in a cup
Your favorite XYZ Ice Cream
Now in convenient single-serve cups.
Delight in a cup
Your favorite XYZ Ice Cream
Now in convenient single-serve cups.
I took a look at the cup.
Seemed kind of big for a single serving.
I picked one up to read the nutritional information.
Servings per container: 2