{"id":4963,"date":"2013-03-13T07:00:00","date_gmt":"2013-03-13T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/03\/13\/closing-holes-in-the-update-notification-pattern\/"},"modified":"2013-03-13T07:00:00","modified_gmt":"2013-03-13T07:00:00","slug":"closing-holes-in-the-update-notification-pattern","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20130313-00\/?p=4963","title":{"rendered":"Closing holes in the update notification pattern"},"content":{"rendered":"<p><P>\nSuppose you have a function that is registered to be called\nthe next time something gets updated,\nand suppose that the notification is a one-shot\nnotification and\nneeds to be re-armed each time you want to\nwait for the next notification<\/A>.\n(For example, the\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/ms724892.aspx\">\n<CODE>Reg&shy;Notify&shy;Change&shy;Key&shy;Value<\/CODE><\/A>\nfunction behaves this way.)\nConsider the following code fragment:\n<\/P>\n<PRE>\n<I>void onUpdateThing()\n{\n \/\/ get the updated properties of the thing\n getThingProperties();<\/p>\n<p> \/\/ ask to be called back the next time it updates\n registerUpdateCallback(onUpdateThing);\n}<\/I><\/p>\n<p>mainProgram()\n{\n \/\/ get the thing&#8217;s initial properties\n \/\/ and register for updates\n onUpdateThing();\n}\n<\/PRE>\n<P>\nThere is a race condition here if the thing updates\ntwice in rapid succession.\nOn the first update, your <CODE>onUpdateThing<\/CODE>\nfunction is called.\nIf the second update occurs\n<I>while <CODE>get&shy;Thing&shy;Properties<\/CODE> is running<\/I>,\nthen your call to\n<CODE>register&shy;Update&shy;Callback<\/CODE> will be too late,\nand you will miss the second update.\n<\/P>\n<P>\nThe solution is to register for the next update <I>before<\/I>\nstudying the previous one.\n<\/P>\n<PRE>\nvoid onUpdateThing()\n{\n \/\/ ask to be called back the next time it updates\n registerUpdateCallback(onUpdateThing);<\/p>\n<p> \/\/ get the updated properties of the thing\n getThingProperties();\n}\n<\/PRE>\n<P>\nThat way, if a second update comes in while you&#8217;re studying\nthe first one,\nyour update callback will be called because you already\nregistered it.\n(I&#8217;m assuming you&#8217;re only interested in the last update.)\n<\/P>\n<P>\nOf course, this assumes that update requests are queued\nif the receiving thread is busy.\nIf updates can be received during the execution of\n<CODE>get&shy;Thing&shy;Properties<\/CODE>,\nthen you will end up in a bad re-entrant situation:\nDuring the processing of one update,\nyou start processing a new update.\nThen when the nested update finishes,\nyou return to the original update,\nwhich is now actually performing the second half\nof the second update.\n<\/P>\n<P>\nSuppose your update code wants to keep the colors\nof two additional objects in sync with the color\nof the thing:\n<\/P>\n<PRE>\nvoid getThingProperties()\n{\n Color currentThingColor = getThingColor();\n object1.setColor(currentThingColor);\n object2.setColor(currentThingColor);\n}\n<\/PRE>\n<P>\nIf the <CODE>set&shy;Color<\/CODE> method\ncreates a re-entrancy window, you can have this problem:\n<\/P>\n<UL>\n<LI>Thing changes color to red.\n<LI><CODE>on&shy;Update&shy;Thing<\/CODE> begins.\n<LI>Register update callback.\n<LI><CODE>get&shy;Thing&shy;Properties<\/CODE> reads\n    current color as red.\n<LI><CODE>get&shy;Thing&shy;Properties<\/CODE>\n    sets object&nbsp;1&#8217;s color to red.\n    The <CODE>set&shy;Color<\/CODE> method\n    creates an opportunity for re-entrancy\n    by some means.\n    (For example, it may send a message to another thread,\n    causing inbound sent messages to be processed.)\n<UL>\n    <LI>Thing changes color to blue.\n    <LI><CODE>on&shy;Update&shy;Thing<\/CODE> begins.\n    <LI>Register update callback.\n    <LI><CODE>get&shy;Thing&shy;Properties<\/CODE> reads\n        current color as blue.\n    <LI><CODE>get&shy;Thing&shy;Properties<\/CODE>\n        sets object&nbsp;1&#8217;s color to blue.\n    <LI><CODE>get&shy;Thing&shy;Properties<\/CODE>\n        sets object&nbsp;2&#8217;s color to blue.\n    <LI><CODE>get&shy;Thing&shy;Properties<\/CODE> returns.\n    <LI><CODE>on&shy;Update&shy;Thing<\/CODE> returns.\n<\/UL>\n<LI><CODE>get&shy;Thing&shy;Properties<\/CODE>\n    sets object&nbsp;2&#8217;s color to <I>red<\/I>. (Oops.)\n<LI><CODE>get&shy;Thing&shy;Properties<\/CODE> returns.\n<LI><CODE>on&shy;Update&shy;Thing<\/CODE> returns.\n<\/UL>\n<P>\nOne solution is to use a\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/ms649042.aspx\">\nsequence number<\/A> (also known as a\n<A HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/04\/12\/10152296.aspx\">\nchange counter<\/A>)\nthat gets incremented each time the thing changes.\nIf there is only one thread which updates the thing,\nyou can try to update it atomically.\nFor example, if the information is in the registry,\nyou can\nput all the information into a single registry value\nor use registry transactions.\n<\/P>\n<P>\nIf you can associate a change counter with the data,\nthen you can use the following algorithm:\n<\/P>\n<PRE>\n\/\/ start with a known invalid value\n\/\/ (If you have multiple listeners, then this naturally\n\/\/ needs to be instance data rather than global.)\nLONG lLastChange = 0;<\/p>\n<p>void onUpdateThing()\n{\n bool finished = false;\n do {\n  \/\/ record the most recent change we&#8217;ve processed\n  lLastChange = getThingChangeCount();<\/p>\n<p>  getThingProperties();<\/p>\n<p>  \/\/ ask to be called back the next time it updates\n  registerUpdateCallback(onUpdateThing);<\/p>\n<p>  \/\/ did it change while we were busy?\n  LONG lNewChange = getThingChangeCount();<\/p>\n<p>  finished = lLastChange == lNewChange;\n  if (!finished) {\n   \/\/ cancel the update callback because we don&#8217;t\n   \/\/ want to be re-entered\n   unregisterUpdateCallback(onUpdateThing);\n  }\n } while (!finished);\n}\n<\/PRE>\n<P>\nAnother solution would be to detect the re-entrancy and just\nremember that there is more work to be done after\nthe previous update finishes.\n<\/P>\n<PRE>\n\/\/ 0 = not busy\n\/\/ 1 = busy\n\/\/ 2 = busy, and a change occurred while we were busy\n\/\/ (If you have multiple listeners, then this naturally\n\/\/ needs to be instance data rather than global.)\nint iBusy = 0;<\/p>\n<p>void onUpdateThing()\n{\n \/\/ ask to be called back the next time it updates\n registerUpdateCallback(onUpdateThing);<\/p>\n<p> if (iBusy) {\n   iBusy = 2;\n } else {\n  iBusy = 1;\n  do {\n   getThingProperties();\n  } while (&#8211;iBusy);\n }\n}\n<\/PRE>\n<P>\nNote that all of the above examples assume that the\n<CODE>on&shy;Update&shy;Thing<\/CODE> function\nhas thread affinity.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Suppose you have a function that is registered to be called the next time something gets updated, and suppose that the notification is a one-shot notification and needs to be re-armed each time you want to wait for the next notification. (For example, the Reg&shy;Notify&shy;Change&shy;Key&shy;Value function behaves this way.) Consider the following code fragment: void [&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-4963","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Suppose you have a function that is registered to be called the next time something gets updated, and suppose that the notification is a one-shot notification and needs to be re-armed each time you want to wait for the next notification. (For example, the Reg&shy;Notify&shy;Change&shy;Key&shy;Value function behaves this way.) Consider the following code fragment: void [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/4963","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=4963"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/4963\/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=4963"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=4963"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=4963"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}