Locally Unique ID


Sometimes you need a locally unique identifier. For example, you may want to create a temporary file but there may have may instances of your code running, and you don’t want any of them to conflict on the file name.


You can try with a random file name, and call CreateFile on it. If CreateFile returns that the file has already exist, you try with a new name. If the file name is random enough, the collision will be small.


Or, you can create something almost guarantee to be locally unique.


Time only moves forward. The current system time is a good candidate for it.


On any given time, there could be multiple processes running. You need to distinguish those processes. The process ID is the obvious choice.


On a running process, you need something to separate the potential multiple thread. Thread ID is a good fit.


So, Current System Time + Process ID + Thread ID is a very good candidate for such locally unique identifier.


But it is not perfect, because the Current System Time does not have enough precision. It is possible that within the smallest measurement of the system time, a process will exist, and a new process will start with the same Process ID as the old process (and the same Thread ID). But the chance is so rare that you may not need to worry about it.

Comments (9)

  1. Isn’t ThreadID already unique on the system? Why do you include both ProcessID and ThreadID ?

    How about the results of QueryPerformaceCounter()? They are high-resolution (64-bit) timers and very unique (they change after each CPU instuction). The docs say that not all CPUs support it, but I’ve never found any one which had any problems with that.

    Besides – why not just use GUIDs?

    Jarek

  2. ThreadID is unique in Windows but may not be in other OSes.

    I was going to use QPC. But the documentation says in multi-cpu configuration, each CPU may return different QPC, which does not follow my pattern of unique id generation. Plus I am not sure if it is supported on other OSes.

    I did not worry about fibers. If you do you probably want to add another variable.

    GUID is unique, but it is not really easy to generate. I want something quick and dirty. And the RPCRT4.dll dependency is a killer.

  3. Luciano says:

    The standard C way: tmpnam()

  4. Is there a reason you can’t use

    GetTempFileName() ?

  5. I was just using the file name as an example. I may use this for other purpose.

  6. JohnT says:

    Why not just use Guid.NewGuid().ToString()? If you don’t like the dashes in the name then supply a different format, Guid.NewGuid().ToString("N") for instance. FYI, Guid uses many of the same mechanics that you’ve already mentioned such as a time factor to insure uniqueness. If a GUID is guaranteed to be Globally Unique, then it will be Locally Unique as well. Now is if you want a more compact version try:

    string uniqueName = Convert.ToBase64String(Guid.NewGuid().ToByteArray());

    — Enjoy

  7. Also GetTempFileName() does not work well if what I want is a directory name.

  8. Like others mentioned, I use Guid. If I have to use a specific filename in a temp folder for whatever reason (like when working with Outlook attachments) I’ll create a folder named with a Guid and store the file in that folder.

    I also created a very simple stream-wrapper that cleans up the temp file on Dispose by deleting the temp file and folder. Guess I’m getting off the original topic.

  9. Jay says:

    Junfeng you claim that time only moves forward. That is false. Time jumps around arbitrarily as the user sets it in the control panel.

    Also you mention pids/tids being recycled. If your code is actually running and creating a file, its own pid/tid will not be recycled, as they’d still be in use.