{"id":30993,"date":"2006-06-02T10:00:00","date_gmt":"2006-06-02T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/06\/02\/what-does-the-cs_classdc-class-style-do\/"},"modified":"2006-06-02T10:00:00","modified_gmt":"2006-06-02T10:00:00","slug":"what-does-the-cs_classdc-class-style-do","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060602-00\/?p=30993","title":{"rendered":"What does the CS_CLASSDC class style do?"},"content":{"rendered":"<p>\nLast time, I talked about the historical background for\nthe <code>CS_OWNDC<\/code> class style and why it starts out\nsounding like a good idea but when you think about it some more\nturns out to be an awful idea.\n<\/p>\n<p>\nThe <code>CS_CLASSDC<\/code> class style is the same thing, but worse,\nfor it takes all the problems of <code>CS_OWNDC<\/code> and magnifies them.\nRecall that the <code>CS_OWNDC<\/code> class style instructs the window\nmanager to create a DC for the window and use that single DC in response\nto calls to <code>BeginPaint<\/code> and <code>GetDC<\/code>.\nThe <code>CS_CLASSDC<\/code> takes this one step further and\ncreates a DC for <strong>all the windows of that class<\/strong>.\nSo that problem I showed last time with a function that thought\nit had two different DCs for a window can now happen even\nacross windows.\nYou think you have one DC for one window and another DC for another\nwindow, but in fact they are the same!\n<\/p>\n<p>\nWhat makes this even worse is that two threads can both be using\nthe same DC at the same time.\nThere is nothing in GDI to forbid it;\nit&#8217;s simply a race to see which thread&#8217;s changes prevail:\n&#8220;Last writer wins.&#8221;\nImagine two threads that happen each to have a <code>CS_CLASSDC<\/code>\nwindow from the same window class,\nand suppose both windows need to be repainted.\nEach window gets a <code>WM_PAINT<\/code> message, and the two\nthreads both go into their painting code.\nBut what these threads don&#8217;t know is that they are operating on\nthe <strong>same DC<\/strong>.\n<\/p>\n<table>\n<tr>\n<th>Thread&nbsp;A<\/th>\n<th>Thread&nbsp;B<\/th>\n<\/tr>\n<tr>\n<td>HDC hdc = BeginPaint(hwnd, &amp;ps);<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>HDC hdc = BeginPaint(hwnd, &amp;ps);<\/td>\n<\/tr>\n<tr>\n<td>SetTextColor(hdc, red);<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>SetTextColor(hdc, blue);<\/td>\n<\/tr>\n<tr>\n<td>DrawText(hdc, &#8230;);<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td>DrawText(hdc, &#8230;);<\/td>\n<\/tr>\n<\/table>\n<p>\nThe code running in Thread&nbsp;A\nfully expected the text to be in red since it set the text color\nto red and then drew text.\nHow was it to know that just at that moment,\nThread&nbsp;B went and changed it to blue?\n<\/p>\n<p>\nThis is the sort of race condition bug that you&#8217;ll probably never\nbe able to study under controlled conditions.\nYou&#8217;ll just get bug reports from customers saying that\nmaybe once a month, an item comes out the wrong color, and maybe you&#8217;ll\nsee it yourself once in a while, but it will never happen when\nyou have debugger breakpoints set.\nEven if you add additional diagnostic code, all you&#8217;ll see is this:\n<\/p>\n<pre>\n...\nSetTextColor(hdc, red);\nASSERT(GetTextColor(hdc) == red); <font COLOR=\"blue\">\/\/ assertion fires!<\/font>\nDrawText(hdc, ...);\n<\/pre>\n<p>\nGreat, the assertion fired.\nThe color you just set isn&#8217;t there.\nNow what are you going to do?\nMaybe you&#8217;ll just say &#8220;Stupid buggy Windows&#8221; and change your\ncode to<\/p>\n<pre>\n\/\/ Stupid buggy Windows. For some reason,\n\/\/ about once a month, the SetTextColor doesn't\n\/\/ work and we have to call it twice.\ndo {\n SetTextColor(hdc, red);\n} while (GetTextColor(hdc) != red);\nDrawText(hdc, ...);\n<\/pre>\n<p>\nAnd even that doesn&#8217;t fix the problem, because\nThread&nbsp;B might have changed the color to blue\nafter the <code>GetTextColor<\/code> and the call to <code>DrawText<\/code>.\nNow, it&#8217;s only once every six months that the item comes out the\nwrong color.\n<\/p>\n<p>\nYou swear at Microsoft and vow to develop Mac software from now on.\n<\/p>\n<p>\nOkay, so now I hope I&#8217;ve convinced you that <code>CS_CLASSDC<\/code> is\na horrifically bad idea.\nBut if it&#8217;s so fundamentally flawed,\nwhy does it exist in the first place?\n<\/p>\n<p>\nBecause 16-bit Windows is co-operatively multi-tasked.\nIn the 16-bit world, you don&#8217;t have to worry about another thread\nsneaking in and messing with your DC because, as I already noted,\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2005\/06\/27\/432303.aspx\">\nthe fact that you were running meant that nobody else was running<\/a>.\nThis whole multi-threaded disaster scenario could not occur,\nso <code>CS_CLASSDC<\/code> is only slightly wackier than\n<code>CS_OWNDC<\/code>.\nThe introduction of pre-emptive multi-tasking with multiple threads\nin a single process is what\ntook us into the world of &#8220;this has no chance of ever working\nproperly&#8221;.\nThe class style exists so people who used it in 16-bit code\ncan port to Win32 (as long as they promise to remain a single-threaded\napplication),\nbut no modern software should use it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time, I talked about the historical background for the CS_OWNDC class style and why it starts out sounding like a good idea but when you think about it some more turns out to be an awful idea. The CS_CLASSDC class style is the same thing, but worse, for it takes all the problems of [&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,2],"class_list":["post-30993","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code","tag-history"],"acf":[],"blog_post_summary":"<p>Last time, I talked about the historical background for the CS_OWNDC class style and why it starts out sounding like a good idea but when you think about it some more turns out to be an awful idea. The CS_CLASSDC class style is the same thing, but worse, for it takes all the problems of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30993","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=30993"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30993\/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=30993"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=30993"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=30993"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}