{"id":4096,"date":"2010-10-13T12:59:48","date_gmt":"2010-10-13T17:59:48","guid":{"rendered":"http:\/\/bobbeaty.com\/wp\/?p=4096"},"modified":"2010-10-14T08:15:22","modified_gmt":"2010-10-14T13:15:22","slug":"preserving-iterators-on-fast-lockless-caches-use-the-trash","status":"publish","type":"post","link":"https:\/\/bobbeaty.com\/wp\/archives\/4096","title":{"rendered":"Preserving Iterators on Fast, Lockless, Caches &#8211; Use the Trash"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/bobbeaty.com\/wp\/wp-content\/uploads\/2008\/03\/generaldev.jpg\" alt=\"GeneralDev.jpg\" title=\"GeneralDev.jpg\" border=\"0\" width=\"128\" height=\"128\" style=\"float:right;\" \/><\/p>\n<p>This was actually the most fun part of my day. I was worried about how to allow the quick cache's clients to run iterators over the cache data and <em>not<\/em> get nailed when the data in the cache is updated by the exchange feed. In general, it's hard to imagine. You have a cache that <strong><em>by design<\/em><\/strong> doesn't lock or notify anyone, and a reader that also <em>by design<\/em> is going to be slower than the ticker feed and will, very likely, always be looking at the <em>entire<\/em> cache and getting into a lot of trouble with it's iterators.<\/p>\n<p>I was trying to think of a clever solution to the problem when I had another really nice <em>eureka!<\/em> moment: What I'd have is a temporary \"trash can\", and when the client asks to keep things \"stable\", the cache tosses the old values into the \"trash\". When the client is done, it'll \"throw the trash away\", and the cost of the deletes will be on the client's thread.<\/p>\n<p>If I built it with a simple STL <tt>__gnu_cxx::slist<\/tt>, then I'd have a very fast queue. I don't need to have any specific order, just a place to hold these guys until they are no longer needed. So rather than calling <tt>delete<\/tt> on the 'old' message, the <tt>put()<\/tt> method on the cache will instead do a <tt>push_front()<\/tt> to the 'trash' queue. It's fast, clean, and should work wonderfully.<\/p>\n<p>I have two methods that control an atomic boolean. It's a little utility class I wrote that wraps an atomic uint8_t as a simple boolean so it can be toggled\/set\/read atomically:<\/p>\n<pre class=\"cpp\" style=\"font-family:monospace;\">  <span style=\"color: #0000ff;\">void<\/span> QuickCache<span style=\"color: #008080;\">::<\/span><span style=\"color: #007788;\">saveToTrash<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#41;<\/span>\n  <span style=\"color: #008000;\">&#123;<\/span>\n    <span style=\"color: #0000ff;\">if<\/span> <span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #000040;\">!<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #0000ff;\">bool<\/span><span style=\"color: #008000;\">&#41;<\/span>mUsingTrash<span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n      <span style=\"color: #666666;\">\/\/ first, clean out anything that might be lingering in the trash<\/span>\n      Message  <span style=\"color: #000040;\">*<\/span>m <span style=\"color: #000080;\">=<\/span> <span style=\"color: #0000ff;\">NULL<\/span><span style=\"color: #008080;\">;<\/span>\n      <span style=\"color: #0000ff;\">while<\/span> <span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #000040;\">!<\/span>mTrash.<span style=\"color: #007788;\">empty<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#41;<\/span><span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n        <span style=\"color: #0000ff;\">if<\/span> <span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#40;<\/span>m <span style=\"color: #000080;\">=<\/span> mTrash.<span style=\"color: #007788;\">front<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#41;<\/span><span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #000040;\">!<\/span><span style=\"color: #000080;\">=<\/span> <span style=\"color: #0000ff;\">NULL<\/span><span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n          <span style=\"color: #0000dd;\">delete<\/span> m<span style=\"color: #008080;\">;<\/span>\n        <span style=\"color: #008000;\">&#125;<\/span>\n        mTrash.<span style=\"color: #007788;\">pop_front<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#41;<\/span><span style=\"color: #008080;\">;<\/span>\n      <span style=\"color: #008000;\">&#125;<\/span>\n      <span style=\"color: #666666;\">\/\/ now set the flag that indicates that the trash is ready to use<\/span>\n      mUsingTrash <span style=\"color: #000080;\">=<\/span> <span style=\"color: #0000ff;\">true<\/span><span style=\"color: #008080;\">;<\/span>\n    <span style=\"color: #008000;\">&#125;<\/span>\n  <span style=\"color: #008000;\">&#125;<\/span>\n&nbsp;\n&nbsp;\n  <span style=\"color: #0000ff;\">void<\/span> QuickCache<span style=\"color: #008080;\">::<\/span><span style=\"color: #007788;\">takeOutTrash<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#41;<\/span>\n  <span style=\"color: #008000;\">&#123;<\/span>\n    <span style=\"color: #0000ff;\">if<\/span> <span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #0000ff;\">bool<\/span><span style=\"color: #008000;\">&#41;<\/span>mUsingTrash<span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n      <span style=\"color: #666666;\">\/\/ first, set the flag that indicates that the trash is NOT in use<\/span>\n      mUsingTrash <span style=\"color: #000080;\">=<\/span> <span style=\"color: #0000ff;\">false<\/span><span style=\"color: #008080;\">;<\/span>\n      <span style=\"color: #666666;\">\/\/ next, clean out anything that might be lingering in the trash now<\/span>\n      Message  <span style=\"color: #000040;\">*<\/span>m <span style=\"color: #000080;\">=<\/span> <span style=\"color: #0000ff;\">NULL<\/span><span style=\"color: #008080;\">;<\/span>\n      <span style=\"color: #0000ff;\">while<\/span> <span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #000040;\">!<\/span>mTrash.<span style=\"color: #007788;\">empty<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#41;<\/span><span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n        <span style=\"color: #0000ff;\">if<\/span> <span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#40;<\/span>m <span style=\"color: #000080;\">=<\/span> mTrash.<span style=\"color: #007788;\">front<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#41;<\/span><span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #000040;\">!<\/span><span style=\"color: #000080;\">=<\/span> <span style=\"color: #0000ff;\">NULL<\/span><span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n          <span style=\"color: #0000dd;\">delete<\/span> m<span style=\"color: #008080;\">;<\/span>\n        <span style=\"color: #008000;\">&#125;<\/span>\n        mTrash.<span style=\"color: #007788;\">pop_front<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#41;<\/span><span style=\"color: #008080;\">;<\/span>\n      <span style=\"color: #008000;\">&#125;<\/span>\n    <span style=\"color: #008000;\">&#125;<\/span>\n  <span style=\"color: #008000;\">&#125;<\/span><\/pre>\n<p>And then in my <tt>put()<\/tt> method, when I'd normally have deleted the 'old' message from the cache, I simply:<\/p>\n<pre class=\"cpp\" style=\"font-family:monospace;\">  <span style=\"color: #666666;\">\/\/ the new one is in the cache - let's dispose of the old one<\/span>\n  <span style=\"color: #0000ff;\">if<\/span> <span style=\"color: #008000;\">&#40;<\/span>oldMsg <span style=\"color: #000040;\">!<\/span><span style=\"color: #000080;\">=<\/span> <span style=\"color: #0000ff;\">NULL<\/span><span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n    <span style=\"color: #0000ff;\">if<\/span> <span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #008000;\">&#40;<\/span><span style=\"color: #0000ff;\">bool<\/span><span style=\"color: #008000;\">&#41;<\/span>mUsingTrash<span style=\"color: #008000;\">&#41;<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n      mTrash.<span style=\"color: #007788;\">push_front<\/span><span style=\"color: #008000;\">&#40;<\/span>oldMsg<span style=\"color: #008000;\">&#41;<\/span><span style=\"color: #008080;\">;<\/span>\n    <span style=\"color: #008000;\">&#125;<\/span> <span style=\"color: #0000ff;\">else<\/span> <span style=\"color: #008000;\">&#123;<\/span>\n      <span style=\"color: #0000dd;\">delete<\/span> oldMsg<span style=\"color: #008080;\">;<\/span>\n    <span style=\"color: #008000;\">&#125;<\/span>\n    oldMsg <span style=\"color: #000080;\">=<\/span> <span style=\"color: #0000ff;\">NULL<\/span><span style=\"color: #008080;\">;<\/span>\n  <span style=\"color: #008000;\">&#125;<\/span><\/pre>\n<p>I haven't had a real chance to test it, but I'm hoping that tomorrow morning when I get ticks from the exchanges, I'll be able to see that this is going to work. If not, then it's back to the drawing board and figure something <em>else<\/em> out.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This was actually the most fun part of my day. I was worried about how to allow the quick cache&#8217;s clients to run iterators over the cache data and not get nailed when the data in the cache is updated by the exchange feed. In general, it&#8217;s hard to imagine. You have a cache that [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,6],"tags":[],"class_list":["post-4096","post","type-post","status-publish","format-standard","hentry","category-coding","category-cube-life"],"_links":{"self":[{"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/posts\/4096","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/comments?post=4096"}],"version-history":[{"count":3,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/posts\/4096\/revisions"}],"predecessor-version":[{"id":4101,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/posts\/4096\/revisions\/4101"}],"wp:attachment":[{"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/media?parent=4096"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/categories?post=4096"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bobbeaty.com\/wp\/wp-json\/wp\/v2\/tags?post=4096"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}