{"id":43843,"date":"2014-10-15T07:00:00","date_gmt":"2014-10-15T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/10\/15\/the-getcurrentthread-function-is-like-a-check-payable-to-bearer-what-it-means-depends-on-whos-holding-it\/"},"modified":"2014-10-15T07:00:00","modified_gmt":"2014-10-15T07:00:00","slug":"the-getcurrentthread-function-is-like-a-check-payable-to-bearer-what-it-means-depends-on-whos-holding-it","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20141015-00\/?p=43843","title":{"rendered":"The GetCurrentThread function is like a check payable to Bearer: What it means depends on who&#039;s holding it"},"content":{"rendered":"<p>\nThe <code>Get&shy;Current&shy;Thread<\/code> function\nreturns a pseudo-handle to the current thread.\nThe documentation\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms683182(v=vs.85).aspx\">\ngoes into significant detail<\/a>\non what this means,\nbut I fear that it may have fallen into the trap of providing\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2013\/04\/10\/10409822.aspx\">\nso much documentation that people decide to skip it<\/a>.\n<\/p>\n<p>\nOkay, so first of all, what is a pseudo-handle?\na pseudo-handle is a sentinel value for <code>HANDLE<\/code>\nthat is not really a handle, but it can act like one.\n<\/p>\n<p>\nThe pseudo-handle returned by <code>Get&shy;Current&shy;Thread<\/code>\nmeans,\n&#8220;The thread that this code is running on.&#8221;\nNote that <i>this is a context-sensitive proposition<\/i>.\nAll the text in MSDN is explaining the consequences of that\nsentence.\n<\/p>\n<p>\nIn a sense, the\n<code>Get&shy;Current&shy;Thread<\/code> function is like a GPS:\nIt tells you where you <i>are<\/i>,\nnot where you <i>were<\/i>.\n<\/p>\n<p>\nImagine somebody who had never seen a GPS before.\nWhen they park their car in a parking garage,\nthey look at the parking level number printed on the wall\nand write it down.\nThen when somebody asks,\n&#8220;Where did you park your car?&#8221;\nthey can look in their notebook and say,\n&#8220;Oh, it&#8217;s on level 3.&#8221;\nSome parking garages even have little pads of paper with\nthe parking level pre-printed on it.\nWhen you park your car, you tear a piece of paper off the pad\nand tuck it into your purse or wallet.\nThen when you want to return to your car,\nyou see the slip of paper,\nand it tells you where you parked.\n<\/p>\n<p>\nNow suppose you hand that person a GPS device,\nand tell them,\n&#8220;This will tell you your current location.&#8221;\n<\/p>\n<p>\n&#8220;Great! My current location is level 3 of the parking garage.&#8221;\n<\/p>\n<p>\nThey go out shopping or whatever they were planning on\ndoing, and now it&#8217;s time to go home.\nThey can&#8217;t remember where they parked, so they\nlook at the device, and it says,\n&#8220;Your current location is 512 Main Street.&#8221;\n<\/p>\n<p>\n&#8220;Hey, you told me this told me where I parked my car.&#8221;\n<\/p>\n<p>\n&#8220;No, I said that it told your current location.&#8221;\n<\/p>\n<p>\n&#8220;That&#8217;s right.\nAnd at the time you gave it to me,\nmy current location was level 3 of the parking garage.\nSo I expect it to say &#8216;Level 3 of the parking garage&#8217;.&#8221;\n<\/p>\n<p>\n&#8220;No, I mean it tells you your current location\nat the time you look at it.&#8221;\n<\/p>\n<p>\n&#8220;Well, that&#8217;s stupid. I can do that too.&#8221;\n(Scribble.)\n&#8220;There, it&#8217;s a piece of paper that says\n&#8216;You are right here&#8217;.&#8221;\n<\/p>\n<p>\nThe value returned by the\n<code>Get&shy;Current&shy;Thread<\/code> function is like the GPS,\nor the slip of paper that says\n&#8220;You are right here.&#8221;\nWhen you hand that value to the kernel,\nit substitutes the current thread\nat the time you use it.\nIt&#8217;s like a check payable to Bearer:\nThe money goes to whoever happens to take it to the bank.\n<\/p>\n<p>\nThis means, for example, that if you\ncall\n<code>Get&shy;Current&shy;Thread<\/code> from one thread and pass the\nresult to another thread,\nthen when that other thread uses the\nvalue, the kernel will interpret\nto mean the thread that is using it,\nnot the thread that called <code>Get&shy;Current&shy;Thread<\/code>.\n<\/p>\n<p>\nIt also means that the value cannot\nbe meaningfully cached to remember\nthe thread that created the value,\nbecause the point of <code>Get&shy;Current&shy;Thread<\/code> is to adapt\nto whoever happens to be using it.\n<\/p>\n<p>\nThe theory behind <code>Get&shy;Current&shy;Thread<\/code> and its friend\n<code>Get&shy;Current&shy;Process<\/code>\nis that it gives you a convenient way to refer\nto the current thread from the current thread\nor the current process from the current process.\nFor example, you might pass the return value of\n<code>Get&shy;Current&shy;Process<\/code>\nto\n<code>Duplicate&shy;Handle<\/code> in order to\nduplicate a handle into or out of the current process.\nOr you might pass the return value of <code>Get&shy;Current&shy;Thread<\/code>\nto\n<code>Set&shy;Thread&shy;Priority<\/code> to change the priority of\nthe current thread.\nThe &#8220;current thread&#8221; pseudo-handle let you simplify this:\n<\/p>\n<pre>\nBOOL SetCurrentThreadPriority(int nPriority)\n{\n BOOL fSuccess = FALSE;\n HANDLE hCurrentThread = OpenThread(THREAD_SET_INFORMATION,\n                            FALSE, GetCurrentThreadId());\n if (hCurrentThread)\n {\n  fSuccess = SetThreadPriority(hCurrentThread, nPriority);\n  CloseHandle(hCurrentThread);\n}\n<\/pre>\n<p>\nto\n<\/p>\n<pre>\nBOOL SetCurrentThreadPriority(int nPriority)\n{\n return SetThreadPriority(GetCurrentThread(), nPriority);\n}\n<\/pre>\n<p>\nIf you want to convert a pseudo-handle to a real handle,\nyou can use the\n<code>Duplicate&shy;Handle<\/code> function.\n<\/p>\n<pre>\nBOOL ConvertToRealHandle(HANDLE h,\n                         BOOL bInheritHandle,\n                         HANDLE *phConverted)\n{\n return DuplicateHandle(GetCurrentProcess(), h,\n                        GetCurrentProcess(), phConverted,\n                        0, bInheritHandle, DUPLICATE_SAME_ACCESS);\n}\nBOOL GetCurrentThreadHandle(BOOL bInheritHandle, HANDLE *phThread)\n{\n return ConvertToRealHandle(GetCurrentThread(), bInheritHandle, phThread);\n}\nBOOL GetCurrentProcessHandle(BOOL bInheritHandle, HANDLE *phProcess)\n{\n return ConvertToRealHandle(GetCurrentProcess(), bInheritHandle, phProcess);\n}\n<\/pre>\n<p>\nArmed with your knowledge of pseudo-handles,\ncriticize the following code:\n<\/p>\n<pre>\nclass CSingleThreadedObject\n{\npublic:\n CSingleThreadedObject() : _hThreadCreated(GetCurrentThread()) { }\n bool OnCorrectThread() { return GetCurrentThread() == _hThreadCreated; }\nprivate:\n HANDLE _hThreadCreated;\n};\nclass CFoo : protected CSingleThreadedObject\n{\npublic:\n CFoo() { ... }\n \/\/ Every method of CFoo checks whether it is being called on the\n \/\/ same thread that it was created from.\n bool Snap()\n {\n  if (!OnCorrectThread()) return false; \/\/ multithreading not supported\n  ...\n }\n};\n<\/pre>\n<p>\n<b>Follow-up exercise<\/b>:\nCriticize the following code that attempts to address the issues\nyou raised in the previous exercise.\n<\/p>\n<pre>\n\/\/ ignore error handling in this class for the purpose of the exercise\nclass CSingleThreadedObject\n{\npublic:\n CSingleThreadedObject() {\n  ConvertToRealHandle(GetCurrentThread(), FALSE, &amp;_hThreadCreated)\n}\n bool OnCorrectThread() {\n  HANDLE hThreadCurrent;\n  ConvertToRealHandle(GetCurrentThread(), FALSE, &amp;hThreadCurrent);\n  bool onCorrectThread = hThreadCurrent == _hThreadCreated;\n  CloseHandle(hThreadCurrent);\n  return onCorrectThread;\n }\nprivate:\n HANDLE _hThreadCreated;\n};\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>The Get&shy;Current&shy;Thread function returns a pseudo-handle to the current thread. The documentation goes into significant detail on what this means, but I fear that it may have fallen into the trap of providing so much documentation that people decide to skip it. Okay, so first of all, what is a pseudo-handle? a pseudo-handle is a [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-43843","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>The Get&shy;Current&shy;Thread function returns a pseudo-handle to the current thread. The documentation goes into significant detail on what this means, but I fear that it may have fallen into the trap of providing so much documentation that people decide to skip it. Okay, so first of all, what is a pseudo-handle? a pseudo-handle is a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=43843"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43843\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=43843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=43843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=43843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}