Jump to content
  • Advertisement

D Bits

  • entries
  • comments
  • views

Setting Thread Affinity on Windows in D

Sign in to follow this  


When working with D's standard library, it is sometimes necessary to work around missing declarations in the core.sys.windows.windows module. It's a fairly big module as is, but it isn't all-inclusive. If you are doing any heavy-duty Windows development, you'll likely want a third-party Win32 API binding. But if you just need to call a function or two, that's overkill.

A good example of this is the need to lock the timing thread to one core when dealing with the Windows timer on a multi-core machine. This is a well-known solution to the problem of erratic timing results returned by QueryPerformanceCounter. If you are using a library like SDL, which uses QPC under the hood for its timing calls, this is something you ought to consider. Unfortunately, Phobos is currently missing declarations for a couple of function calls and one type that you need to lock the timing thread down.

For many cases, this can be overcome by adding the appropriate declarations where you need them. In other cases, you'll find (particularly when using DMD) that the Win32 import libraries that ship with the compiler are outdated. In that case, you'll either need to generate them yourself or load the function symbols manually via LoadLibrary and friends. Luckily, for setting the thread affinity the solution is easy. Here's a complete example, ripped right out of the module where I use it.

import core.sys.windows.windows;
import std.windows.syserror;

// Declarations missing from the windows module.
alias size_t DWORD_PTR;
DWORD SetThreadAffinityMask(HANDLE,DWORD);

void setThreadAffinity()
void doThrow(string msg)
auto err = GetLastError();
throw new Exception(msg ~ sysErrorString(err));

DWORD_PTR procMask, sysMask;
if(!GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask))
doThrow("GetProcessAffinityMask failure: ");

DWORD_PTR mask = 1;
if(mask & procMask)
if(!SetThreadAffinityMask(GetCurrentThread(), mask))
doThrow("SetThreadAffinityMask failure: ");
throw new Exception("Unexpected affinity mask mismatch.");

Drop this into module or class scope and add the following to an init method somewhere in the same module (or another module if you move setThreadAffinity out of the private block).

[source]version(Windows) setThreadAffinity();[/source]

Notice also that I imported std.windows.syserror, which exposes the sysErrorString function. I'm sure I wasn't the only one who overlooked that module. After years of using D, I only noticed it recently. If you're going to be making Win32 API calls, it will come in handy.
Sign in to follow this  


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!