A window can’t have two timers with the same ID, so how do I assign an ID that nobody else is using?

Raymond Chen

The Set­Timer function creates a timer associated with a window. Timer IDs need to be unique, but if you have multiple pieces of code that all want to register a timer on the same window, you need to make sure they all come up with different timer IDs.

One way is to carve up the timer ID space so different components are assigned different ranges of timer IDs. But this means that if you add a new component, you’ll have to assign it a new range of IDs, and you might run into the case where you’ve given away all the available values, and there are no more left to hand out.

And then there are components which may want to create timers on windows they didn’t create. For example, you may have a windowless controls framework, and those windowless controls may need a timer, but they don’t have a window to associate with the timer. They’ll have to somehow share the timer ID space of the windowed host without explicitly coordinating with each other.

A common solution is to use a pointer to ensure a unique number.

According to this convention, if you need a unique ID for a timer, just allocate some memory. You don’t need to allocate memory specifically for this purpose. You probably already allocated some memory, such as memory for your this pointer.

For as long as the memory is allocated, that pointer is uniquely yours. No other object can be assigned the same address, and you can use the pointer as the unique ID.

This technique generalizes to other ID assignment problems, as long as they are constrained to a single address space: For the ID, use the address of something that is uniquely yours.

The memory manager has unwittingly become the ID number registrar.



Discussion is closed. Login to edit/delete existing comments.

  • Reinhard Weiss 0

    Using the this pointer is really a neat trick! How many consecutive IDs could I safely derivate from the this pointer? I assume only 4 if the class has no member variables and the program is compiled for x86.

    • Raymond ChenMicrosoft employee 0

      EBO means that for a class with no member variables, you cannot even assume that your this is unique. Give yourself some member variables and use their addresses.

  • Tom Rothamel 0

    It strikes me that this has an important caveat – the size of your ID has to be larger than or equal to the size of a pointer, or you could plausibly allocate two pointers that are the same in their lower bits. This caveat is true for SetTimer, but might not be true for other IDs that need to be assigned.

  • GSerg 0

    And then there is .NET GC that may move objects around after they are created…

    • Dan Bugglin 0

      Well yeah but you can just use one of the three or four different timer classes built-in and none of them require you to create an ID.

      But if you REALLY needed to, you can use Marshal.AllocHGlobal or whatever to get your unique pointer (assuming nothing else is allocating timers using non-pointer ids).

    • Ian Yates 0

      I’d hope someone who knew how to get pointers of objects in c# and friends was also aware of how the GC works, pins their objects, etc. But even better, doesn’t fight the grain and just uses the built-in stuff that other devs following in their shoes would expect to find

Feedback usabilla icon