{"id":36823,"date":"2005-01-03T07:00:00","date_gmt":"2005-01-03T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/01\/03\/using-fibers-to-simplify-enumerators-part-4-filtering\/"},"modified":"2005-01-03T07:00:00","modified_gmt":"2005-01-03T07:00:00","slug":"using-fibers-to-simplify-enumerators-part-4-filtering","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050103-00\/?p=36823","title":{"rendered":"Using fibers to simplify enumerators, part 4: Filtering"},"content":{"rendered":"<p>\nOne type of higher-order enumeration is filtering,\nwhere one enumerator takes the output of another\nenumerator and removes some elements.\n<\/p>\n<p>\nIn a producer-driven enumerator, you would implement filtering\nby substituting a new callback function that responds to callbacks\non behalf of the client for items that should be filtered,\nand forwarding callbacks to the client for items that are not filtered.\n<\/p>\n<p>\nIn a consumer-driven enumerator, you would implement composition\nby wrapping the enumerator inside another enumerator\nwhich drives the inner enumerator and forwards items that it\nwishes the caller to see.\n<\/p>\n<p>\nA fiber-based enumerator behaves more like a consumer-driven\nenumerator, but,with easier state management.\n<\/p>\n<p>\nLet&#8217;s write a filter enumerator that removes all directories\nand suppresses recursing into them.\n<\/p>\n<pre>\nclass FilteredEnumerator : public FiberEnumerator {\npublic:\n FilteredEnumerator(LPCTSTR pszDir) : m_e(pszDir) { }\n LPCTSTR GetCurDir()\n    { return m_e.GetCurDir(); }\n LPCTSTR GetCurPath()\n    { return m_e.GetCurPath(); }\n const WIN32_FIND_DATA* GetCurFindData()\n    { return m_e.GetCurFindData(); }\nprivate:\n void FiberProc();\nprivate:\n DirectoryTreeEnumerator m_e;\n};\nvoid FilteredEnumerator::FiberProc()\n{\n FEFOUND fef;\n while ((fef = m_e.Next()) != FEF_DONE) {\n  FERESULT fer;\n  if (fef == FEF_DIR) {\n   fer = FER_SKIP; \/\/ don't recurse into directories\n  } else {\n   fer = Produce(fef);\n  }\n  m_e.SetResult(fer);\n }\n}\n<\/pre>\n<p>\nTo produce items from this filtered enumerator,\nwe run the real enumerator (<code>m_e<\/code>)\nand remove all directories, preventing them from\nbeing propagated to the filter&#8217;s consumer and\njust responding &#8220;skip it&#8221; to the real enumerator.\n<\/p>\n<p>\nYou can test out this filtered enumerator with the\nsame <code>TestWalk<\/code> function we&#8217;ve been using\nfor the past few days.  The only change you&#8217;ll need\nto make is to the <code>main<\/code> function:\n<\/p>\n<pre>\nint __cdecl main(int argc, char **argv)\n{\n ConvertThreadToFiber(NULL);\n <font COLOR=\"blue\">FilteredEnumerator e(TEXT(\".\"));<\/font>\n TestWalk(&amp;e);\n ConvertFiberToThread();\n return 0;\n}\n<\/pre>\n<p>\nObserve that the program no longer recurses into\nsubdirectories.  It just tallies the sizes of the\nfiles in the current directory.\n<\/p>\n<p>\nNext time, composition.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One type of higher-order enumeration is filtering, where one enumerator takes the output of another enumerator and removes some elements. In a producer-driven enumerator, you would implement filtering by substituting a new callback function that responds to callbacks on behalf of the client for items that should be filtered, and forwarding callbacks to the client [&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-36823","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>One type of higher-order enumeration is filtering, where one enumerator takes the output of another enumerator and removes some elements. In a producer-driven enumerator, you would implement filtering by substituting a new callback function that responds to callbacks on behalf of the client for items that should be filtered, and forwarding callbacks to the client [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36823","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=36823"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36823\/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=36823"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=36823"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=36823"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}