<html><head><title>Default executor</title><meta content="text/html; charset=UTF-8" http-equiv="content-type"><style type="text/css">.lst-kix_7rtf30mrviy0-6>li:before{content:"\0025cf  "}.lst-kix_ckx1twpwgr4u-4>li:before{content:"\0025cb  "}.lst-kix_4p20v4bilnn5-4>li:before{content:"\0025cb  "}.lst-kix_1yicy4pz0byp-3>li:before{content:"" counter(lst-ctn-kix_1yicy4pz0byp-3,decimal) ". "}.lst-kix_4uiyey1rizlr-0>li:before{content:"" counter(lst-ctn-kix_4uiyey1rizlr-0,upper-latin) ". "}ol.lst-kix_1yicy4pz0byp-7.start{counter-reset:lst-ctn-kix_1yicy4pz0byp-7 0}.lst-kix_ckx1twpwgr4u-1>li:before{content:"\0025cb  "}.lst-kix_1yicy4pz0byp-0>li:before{content:"" counter(lst-ctn-kix_1yicy4pz0byp-0,upper-latin) ". "}.lst-kix_1yicy4pz0byp-8>li:before{content:"" counter(lst-ctn-kix_1yicy4pz0byp-8,lower-roman) ". "}.lst-kix_eqt55ks9wn57-1>li:before{content:"\0025cb  "}.lst-kix_1yicy4pz0byp-5>li:before{content:"" counter(lst-ctn-kix_1yicy4pz0byp-5,lower-roman) ". "}.lst-kix_4p20v4bilnn5-7>li:before{content:"\0025cb  "}.lst-kix_yk3snqicn2bg-5>li:before{content:"\0025a0  "}.lst-kix_hov53iesit5k-8>li:before{content:"\0025a0  "}.lst-kix_yneblgz6qfxk-0>li:before{content:"\0025cf  "}.lst-kix_eqt55ks9wn57-8>li:before{content:"\0025a0  "}.lst-kix_ckx1twpwgr4u-3>li:before{content:"\0025cf  "}.lst-kix_hov53iesit5k-5>li:before{content:"\0025a0  "}ol.lst-kix_4uiyey1rizlr-6.start{counter-reset:lst-ctn-kix_4uiyey1rizlr-6 0}.lst-kix_hov53iesit5k-3>li:before{content:"\0025cf  "}.lst-kix_ckx1twpwgr4u-6>li:before{content:"\0025cf  "}.lst-kix_yneblgz6qfxk-6>li:before{content:"\0025cf  "}.lst-kix_1yicy4pz0byp-1>li:before{content:"" counter(lst-ctn-kix_1yicy4pz0byp-1,lower-latin) ". "}.lst-kix_cqvg0uqbqmz2-6>li:before{content:"\0025cf  "}.lst-kix_cqvg0uqbqmz2-2>li:before{content:"\0025a0  "}ol.lst-kix_1yicy4pz0byp-5.start{counter-reset:lst-ctn-kix_1yicy4pz0byp-5 0}ol.lst-kix_1yicy4pz0byp-2.start{counter-reset:lst-ctn-kix_1yicy4pz0byp-2 0}.lst-kix_1yicy4pz0byp-4>li{counter-increment:lst-ctn-kix_1yicy4pz0byp-4}ol.lst-kix_1yicy4pz0byp-3.start{counter-reset:lst-ctn-kix_1yicy4pz0byp-3 0}ol.lst-kix_4uiyey1rizlr-2.start{counter-reset:lst-ctn-kix_4uiyey1rizlr-2 0}.lst-kix_ckx1twpwgr4u-7>li:before{content:"\0025cb  "}.lst-kix_1yicy4pz0byp-6>li{counter-increment:lst-ctn-kix_1yicy4pz0byp-6}.lst-kix_1yicy4pz0byp-8>li{counter-increment:lst-ctn-kix_1yicy4pz0byp-8}.lst-kix_4uiyey1rizlr-0>li{counter-increment:lst-ctn-kix_4uiyey1rizlr-0}.lst-kix_yk3snqicn2bg-7>li:before{content:"\0025cb  "}ol.lst-kix_1yicy4pz0byp-8.start{counter-reset:lst-ctn-kix_1yicy4pz0byp-8 0}.lst-kix_yneblgz6qfxk-3>li:before{content:"\0025cf  "}ol.lst-kix_1yicy4pz0byp-4.start{counter-reset:lst-ctn-kix_1yicy4pz0byp-4 0}ul.lst-kix_yneblgz6qfxk-8{list-style-type:none}ul.lst-kix_ckx1twpwgr4u-0{list-style-type:none}ul.lst-kix_ckx1twpwgr4u-1{list-style-type:none}.lst-kix_ckx1twpwgr4u-8>li:before{content:"\0025a0  "}.lst-kix_4p20v4bilnn5-5>li:before{content:"\0025a0  "}ul.lst-kix_yneblgz6qfxk-2{list-style-type:none}ul.lst-kix_ckx1twpwgr4u-4{list-style-type:none}ul.lst-kix_yneblgz6qfxk-3{list-style-type:none}ul.lst-kix_ckx1twpwgr4u-5{list-style-type:none}ul.lst-kix_yneblgz6qfxk-0{list-style-type:none}ul.lst-kix_ckx1twpwgr4u-2{list-style-type:none}ul.lst-kix_yneblgz6qfxk-1{list-style-type:none}ul.lst-kix_ckx1twpwgr4u-3{list-style-type:none}.lst-kix_yk3snqicn2bg-3>li:before{content:"\0025cf  "}ul.lst-kix_yneblgz6qfxk-6{list-style-type:none}ul.lst-kix_ckx1twpwgr4u-8{list-style-type:none}ul.lst-kix_yneblgz6qfxk-7{list-style-type:none}ul.lst-kix_yneblgz6qfxk-4{list-style-type:none}ul.lst-kix_ckx1twpwgr4u-6{list-style-type:none}ul.lst-kix_yneblgz6qfxk-5{list-style-type:none}ul.lst-kix_ckx1twpwgr4u-7{list-style-type:none}.lst-kix_eqt55ks9wn57-7>li:before{content:"\0025cb  "}ul.lst-kix_7rtf30mrviy0-8{list-style-type:none}.lst-kix_7rtf30mrviy0-4>li:before{content:"\0025cb  "}.lst-kix_yk3snqicn2bg-0>li:before{content:"\0025cf  "}.lst-kix_1yicy4pz0byp-3>li{counter-increment:lst-ctn-kix_1yicy4pz0byp-3}.lst-kix_eqt55ks9wn57-5>li:before{content:"\0025a0  "}.lst-kix_hov53iesit5k-2>li:before{content:"\0025a0  "}.lst-kix_4uiyey1rizlr-5>li{counter-increment:lst-ctn-kix_4uiyey1rizlr-5}ol.lst-kix_1yicy4pz0byp-1.start{counter-reset:lst-ctn-kix_1yicy4pz0byp-1 0}.lst-kix_4p20v4bilnn5-8>li:before{content:"\0025a0  "}.lst-kix_hov53iesit5k-0>li:before{content:"\0025cf  "}.lst-kix_cqvg0uqbqmz2-5>li:before{content:"\0025a0  "}.lst-kix_yneblgz6qfxk-2>li:before{content:"\0025a0  "}ol.lst-kix_4uiyey1rizlr-1.start{counter-reset:lst-ctn-kix_4uiyey1rizlr-1 0}.lst-kix_ckx1twpwgr4u-2>li:before{content:"\0025a0  "}ol.lst-kix_4uiyey1rizlr-3{list-style-type:none}.lst-kix_1yicy4pz0byp-1>li{counter-increment:lst-ctn-kix_1yicy4pz0byp-1}ol.lst-kix_4uiyey1rizlr-2{list-style-type:none}ol.lst-kix_4uiyey1rizlr-5{list-style-type:none}.lst-kix_hov53iesit5k-7>li:before{content:"\0025cb  "}ol.lst-kix_4uiyey1rizlr-4{list-style-type:none}.lst-kix_cqvg0uqbqmz2-4>li:before{content:"\0025cb  "}ol.lst-kix_4uiyey1rizlr-7{list-style-type:none}ol.lst-kix_4uiyey1rizlr-6{list-style-type:none}ol.lst-kix_4uiyey1rizlr-8{list-style-type:none}ol.lst-kix_1yicy4pz0byp-0.start{counter-reset:lst-ctn-kix_1yicy4pz0byp-0 0}.lst-kix_7rtf30mrviy0-1>li:before{content:"\0025cb  "}.lst-kix_1yicy4pz0byp-4>li:before{content:"" counter(lst-ctn-kix_1yicy4pz0byp-4,lower-latin) ". "}ol.lst-kix_4uiyey1rizlr-1{list-style-type:none}ol.lst-kix_4uiyey1rizlr-0{list-style-type:none}.lst-kix_1yicy4pz0byp-0>li{counter-increment:lst-ctn-kix_1yicy4pz0byp-0}.lst-kix_cqvg0uqbqmz2-3>li:before{content:"\0025cf  "}.lst-kix_yneblgz6qfxk-1>li:before{content:"\0025cb  "}.lst-kix_4uiyey1rizlr-4>li:before{content:"" counter(lst-ctn-kix_4uiyey1rizlr-4,lower-latin) ". "}.lst-kix_7rtf30mrviy0-7>li:before{content:"\0025cb  "}.lst-kix_ckx1twpwgr4u-0>li:before{content:"\0025cf  "}ul.lst-kix_cqvg0uqbqmz2-1{list-style-type:none}.lst-kix_7rtf30mrviy0-0>li:before{content:"\0025cf  "}ul.lst-kix_cqvg0uqbqmz2-0{list-style-type:none}ul.lst-kix_cqvg0uqbqmz2-3{list-style-type:none}ul.lst-kix_cqvg0uqbqmz2-2{list-style-type:none}ul.lst-kix_cqvg0uqbqmz2-5{list-style-type:none}.lst-kix_yneblgz6qfxk-4>li:before{content:"\0025cb  "}ul.lst-kix_cqvg0uqbqmz2-4{list-style-type:none}ul.lst-kix_cqvg0uqbqmz2-7{list-style-type:none}ul.lst-kix_cqvg0uqbqmz2-6{list-style-type:none}ul.lst-kix_cqvg0uqbqmz2-8{list-style-type:none}.lst-kix_yneblgz6qfxk-8>li:before{content:"\0025a0  "}ul.lst-kix_yk3snqicn2bg-4{list-style-type:none}ul.lst-kix_yk3snqicn2bg-3{list-style-type:none}ul.lst-kix_yk3snqicn2bg-2{list-style-type:none}ul.lst-kix_yk3snqicn2bg-1{list-style-type:none}ul.lst-kix_yk3snqicn2bg-8{list-style-type:none}ul.lst-kix_yk3snqicn2bg-7{list-style-type:none}ul.lst-kix_yk3snqicn2bg-6{list-style-type:none}.lst-kix_7rtf30mrviy0-5>li:before{content:"\0025a0  "}ul.lst-kix_yk3snqicn2bg-5{list-style-type:none}ul.lst-kix_yk3snqicn2bg-0{list-style-type:none}.lst-kix_eqt55ks9wn57-6>li:before{content:"\0025cf  "}.lst-kix_4p20v4bilnn5-1>li:before{content:"\0025cb  "}.lst-kix_4uiyey1rizlr-6>li{counter-increment:lst-ctn-kix_4uiyey1rizlr-6}.lst-kix_7rtf30mrviy0-2>li:before{content:"\0025a0  "}.lst-kix_cqvg0uqbqmz2-8>li:before{content:"\0025a0  "}ul.lst-kix_hov53iesit5k-8{list-style-type:none}ul.lst-kix_hov53iesit5k-6{list-style-type:none}ul.lst-kix_hov53iesit5k-7{list-style-type:none}.lst-kix_hov53iesit5k-6>li:before{content:"\0025cf  "}.lst-kix_4uiyey1rizlr-3>li{counter-increment:lst-ctn-kix_4uiyey1rizlr-3}.lst-kix_4uiyey1rizlr-5>li:before{content:"" counter(lst-ctn-kix_4uiyey1rizlr-5,lower-roman) ". "}ul.lst-kix_7rtf30mrviy0-5{list-style-type:none}ul.lst-kix_hov53iesit5k-1{list-style-type:none}ul.lst-kix_7rtf30mrviy0-4{list-style-type:none}ul.lst-kix_hov53iesit5k-0{list-style-type:none}ul.lst-kix_7rtf30mrviy0-7{list-style-type:none}ul.lst-kix_7rtf30mrviy0-6{list-style-type:none}ul.lst-kix_7rtf30mrviy0-1{list-style-type:none}ul.lst-kix_hov53iesit5k-5{list-style-type:none}ul.lst-kix_7rtf30mrviy0-0{list-style-type:none}.lst-kix_4p20v4bilnn5-2>li:before{content:"\0025a0  "}ul.lst-kix_hov53iesit5k-4{list-style-type:none}ol.lst-kix_4uiyey1rizlr-7.start{counter-reset:lst-ctn-kix_4uiyey1rizlr-7 0}ul.lst-kix_7rtf30mrviy0-3{list-style-type:none}ul.lst-kix_hov53iesit5k-3{list-style-type:none}ul.lst-kix_7rtf30mrviy0-2{list-style-type:none}.lst-kix_eqt55ks9wn57-4>li:before{content:"\0025cb  "}ul.lst-kix_hov53iesit5k-2{list-style-type:none}.lst-kix_1yicy4pz0byp-2>li:before{content:"" counter(lst-ctn-kix_1yicy4pz0byp-2,lower-roman) ". "}.lst-kix_1yicy4pz0byp-7>li{counter-increment:lst-ctn-kix_1yicy4pz0byp-7}.lst-kix_ckx1twpwgr4u-5>li:before{content:"\0025a0  "}.lst-kix_4uiyey1rizlr-7>li:before{content:"" counter(lst-ctn-kix_4uiyey1rizlr-7,lower-latin) ". "}.lst-kix_yk3snqicn2bg-1>li:before{content:"\0025cb  "}.lst-kix_1yicy4pz0byp-7>li:before{content:"" counter(lst-ctn-kix_1yicy4pz0byp-7,lower-latin) ". "}ol.lst-kix_1yicy4pz0byp-7{list-style-type:none}.lst-kix_4uiyey1rizlr-3>li:before{content:"" counter(lst-ctn-kix_4uiyey1rizlr-3,decimal) ". "}ol.lst-kix_1yicy4pz0byp-8{list-style-type:none}.lst-kix_1yicy4pz0byp-2>li{counter-increment:lst-ctn-kix_1yicy4pz0byp-2}ol.lst-kix_1yicy4pz0byp-6{list-style-type:none}ol.lst-kix_1yicy4pz0byp-5{list-style-type:none}ol.lst-kix_1yicy4pz0byp-4{list-style-type:none}.lst-kix_7rtf30mrviy0-3>li:before{content:"\0025cf  "}ol.lst-kix_1yicy4pz0byp-3{list-style-type:none}ol.lst-kix_1yicy4pz0byp-2{list-style-type:none}ol.lst-kix_1yicy4pz0byp-1{list-style-type:none}ol.lst-kix_1yicy4pz0byp-0{list-style-type:none}.lst-kix_yneblgz6qfxk-7>li:before{content:"\0025cb  "}ol.lst-kix_4uiyey1rizlr-8.start{counter-reset:lst-ctn-kix_4uiyey1rizlr-8 0}.lst-kix_eqt55ks9wn57-3>li:before{content:"\0025cf  "}.lst-kix_1yicy4pz0byp-6>li:before{content:"" counter(lst-ctn-kix_1yicy4pz0byp-6,decimal) ". "}ol.lst-kix_4uiyey1rizlr-3.start{counter-reset:lst-ctn-kix_4uiyey1rizlr-3 0}.lst-kix_yk3snqicn2bg-8>li:before{content:"\0025a0  "}.lst-kix_yk3snqicn2bg-2>li:before{content:"\0025a0  "}.lst-kix_4uiyey1rizlr-4>li{counter-increment:lst-ctn-kix_4uiyey1rizlr-4}.lst-kix_yneblgz6qfxk-5>li:before{content:"\0025a0  "}.lst-kix_4uiyey1rizlr-6>li:before{content:"" counter(lst-ctn-kix_4uiyey1rizlr-6,decimal) ". "}.lst-kix_4p20v4bilnn5-0>li:before{content:"\0025cf  "}ul.lst-kix_4p20v4bilnn5-5{list-style-type:none}ul.lst-kix_eqt55ks9wn57-2{list-style-type:none}ul.lst-kix_4p20v4bilnn5-6{list-style-type:none}ul.lst-kix_eqt55ks9wn57-1{list-style-type:none}ul.lst-kix_4p20v4bilnn5-7{list-style-type:none}ul.lst-kix_eqt55ks9wn57-0{list-style-type:none}ul.lst-kix_4p20v4bilnn5-8{list-style-type:none}ul.lst-kix_4p20v4bilnn5-1{list-style-type:none}ul.lst-kix_eqt55ks9wn57-6{list-style-type:none}ul.lst-kix_4p20v4bilnn5-2{list-style-type:none}ul.lst-kix_eqt55ks9wn57-5{list-style-type:none}ul.lst-kix_4p20v4bilnn5-3{list-style-type:none}ul.lst-kix_eqt55ks9wn57-4{list-style-type:none}ul.lst-kix_4p20v4bilnn5-4{list-style-type:none}ul.lst-kix_eqt55ks9wn57-3{list-style-type:none}ul.lst-kix_eqt55ks9wn57-8{list-style-type:none}ul.lst-kix_4p20v4bilnn5-0{list-style-type:none}ul.lst-kix_eqt55ks9wn57-7{list-style-type:none}ol.lst-kix_4uiyey1rizlr-4.start{counter-reset:lst-ctn-kix_4uiyey1rizlr-4 0}.lst-kix_4uiyey1rizlr-8>li:before{content:"" counter(lst-ctn-kix_4uiyey1rizlr-8,lower-roman) ". "}.lst-kix_4uiyey1rizlr-7>li{counter-increment:lst-ctn-kix_4uiyey1rizlr-7}ol.lst-kix_4uiyey1rizlr-0.start{counter-reset:lst-ctn-kix_4uiyey1rizlr-0 0}.lst-kix_1yicy4pz0byp-5>li{counter-increment:lst-ctn-kix_1yicy4pz0byp-5}.lst-kix_4p20v4bilnn5-3>li:before{content:"\0025cf  "}.lst-kix_7rtf30mrviy0-8>li:before{content:"\0025a0  "}ol.lst-kix_1yicy4pz0byp-6.start{counter-reset:lst-ctn-kix_1yicy4pz0byp-6 0}.lst-kix_eqt55ks9wn57-0>li:before{content:"\0025cf  "}.lst-kix_4uiyey1rizlr-1>li{counter-increment:lst-ctn-kix_4uiyey1rizlr-1}ol.lst-kix_4uiyey1rizlr-5.start{counter-reset:lst-ctn-kix_4uiyey1rizlr-5 0}.lst-kix_4uiyey1rizlr-2>li:before{content:"" counter(lst-ctn-kix_4uiyey1rizlr-2,lower-roman) ". "}.lst-kix_4uiyey1rizlr-8>li{counter-increment:lst-ctn-kix_4uiyey1rizlr-8}.lst-kix_yk3snqicn2bg-4>li:before{content:"\0025cb  "}.lst-kix_eqt55ks9wn57-2>li:before{content:"\0025a0  "}.lst-kix_cqvg0uqbqmz2-7>li:before{content:"\0025cb  "}.lst-kix_hov53iesit5k-4>li:before{content:"\0025cb  "}.lst-kix_4uiyey1rizlr-2>li{counter-increment:lst-ctn-kix_4uiyey1rizlr-2}.lst-kix_cqvg0uqbqmz2-0>li:before{content:"\0025cf  "}.lst-kix_4p20v4bilnn5-6>li:before{content:"\0025cf  "}.lst-kix_cqvg0uqbqmz2-1>li:before{content:"\0025cb  "}.lst-kix_hov53iesit5k-1>li:before{content:"\0025cb  "}.lst-kix_yk3snqicn2bg-6>li:before{content:"\0025cf  "}.lst-kix_4uiyey1rizlr-1>li:before{content:"" counter(lst-ctn-kix_4uiyey1rizlr-1,lower-latin) ". "}ol{margin:0;padding:0}.c0{widows:2;orphans:2;direction:ltr}.c11{max-width:468pt;background-color:#ffffff;padding:72pt 72pt 72pt 72pt}.c1{padding-left:0pt;margin-left:36pt}.c8{line-height:1.0;padding-bottom:6pt}.c3{margin:0;padding:0}.c9{color:inherit;text-decoration:inherit}.c6{color:#1155cc;text-decoration:underline}.c5{padding-left:0pt;margin-left:72pt}.c10{font-size:14pt;font-family:"Times New Roman"}.c2{height:11pt}.c4{page-break-after:avoid}.c7{font-weight:bold}.title{widows:2;padding-top:0pt;line-height:1.15;orphans:2;text-align:left;color:#000000;font-size:21pt;font-family:"Trebuchet MS";padding-bottom:0pt;page-break-after:avoid}.subtitle{widows:2;padding-top:0pt;line-height:1.15;orphans:2;text-align:left;color:#666666;font-style:italic;font-size:13pt;font-family:"Trebuchet MS";padding-bottom:10pt;page-break-after:avoid}li{color:#000000;font-size:11pt;font-family:"Arial"}p{color:#000000;font-size:11pt;margin:0;font-family:"Arial"}h1{widows:2;padding-top:10pt;line-height:1.15;orphans:2;text-align:left;color:#000000;font-size:16pt;font-family:"Trebuchet MS";padding-bottom:0pt;page-break-after:avoid}h2{widows:2;padding-top:10pt;line-height:1.15;orphans:2;text-align:left;color:#000000;font-size:13pt;font-family:"Trebuchet MS";font-weight:bold;padding-bottom:0pt;page-break-after:avoid}h3{widows:2;padding-top:8pt;line-height:1.15;orphans:2;text-align:left;color:#666666;font-size:12pt;font-family:"Trebuchet MS";font-weight:bold;padding-bottom:0pt;page-break-after:avoid}h4{widows:2;padding-top:8pt;line-height:1.15;orphans:2;text-align:left;color:#666666;font-size:11pt;text-decoration:underline;font-family:"Trebuchet MS";padding-bottom:0pt;page-break-after:avoid}h5{widows:2;padding-top:8pt;line-height:1.15;orphans:2;text-align:left;color:#666666;font-size:11pt;font-family:"Trebuchet MS";padding-bottom:0pt;page-break-after:avoid}h6{widows:2;padding-top:8pt;line-height:1.15;orphans:2;text-align:left;color:#666666;font-style:italic;font-size:11pt;font-family:"Trebuchet MS";padding-bottom:0pt;page-break-after:avoid}</style></head><body class="c11"><p class="c0 c4 title"><a name="h.obqj1dackasq"></a><span>Default executor</span></p><p class="c0 c2"><span></span></p><p class="c0 c8"><span class="c10">ISO/IEC JTC1 SC22 WG21 N4039 - 2014-05-23</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>Adam Berkan (</span><span class="c6"><a class="c9" href="mailto:aberkan@google.com">aberkan@google.com</a></span><span>)</span></p><p class="c0"><span>Chris Mysen (</span><span class="c6"><a class="c9" href="mailto:mysen@google.com">mysen@google.com</a></span><span>)</span></p><p class="c0"><span>Hans Boehm (</span><span class="c6"><a class="c9" href="mailto:hboehm@google.com">hboehm@google.com</a></span><span>)</span></p><p class="c0 c2"><span></span></p><h1 class="c0 c4"><a name="h.fvbv3lub91al"></a><span>Overview</span></h1><p class="c0 c2"><span></span></p><p class="c0"><span>So</span><span>&nbsp;far the standard has been quiet about whether there is a default executor (See n3785 for more about executors). &nbsp;A well-written library that wishes to be flexible should take an executor as a parameter. &nbsp;Unfortunately there is today no good default for that </span><span>library</span><span>. &nbsp;Programmers want a way to run tasks asynchronously without having to create new executors.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>This problem is compounded by the fact that thread pools are often much faster (and use fewer resources) than a thread-per-task executor. &nbsp;Many systems (e.g. Windows) provide a good system thread pool which would be a great default. &nbsp;We would like to make it easy to use that thread pool, but a </span><span>thread pool is generally limited in size and is likely limited in queue depth. &nbsp;This adds new constraints</span><span>&nbsp;to tasks running here, including the number of concurrently blocked threads. &nbsp;There should be a way to specify a real thread-per-task executor for when it is necessary to avoid these constraints.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>An executor that reuses threads could also be faster than a thread-per-task executor, but it would leak thread locals between tasks. &nbsp;Many users would be willing to trade off the leakage for the performance, but this makes it complicated to use thread locals with these executors.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>Another</span><span>&nbsp;related issue is describing where a std::async task runs asynchronously. &nbsp;If we have a default executor, it should be easy to run an async task there. &nbsp;It has been proposed many times (e.g. N3970) to let std::async take an optional executor as an argument. &nbsp;But if no executor is specified, should it run on the std::default_executor? &nbsp;If the default executor has more constraints than a thread-per-task executor, those limitations would then also apply to async. &nbsp;This has the potential to break existing code. &nbsp;Still, most users of async would probably prefer to use a fast thread pool instead of spinning up a thread.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>Beyond all of this (and not discussed in depth here), there&rsquo;s the </span><span>looming promise of fibers</span><span>, and it&rsquo;s uncertain how fibers might be integrated into the standard, and how they would affect executors.</span></p><p class="c0 c2"><span></span></p><h1 class="c0 c4"><a name="h.svhmvy93zekf"></a><span>Design Options</span></h1><p class="c0 c2"><span></span></p><p class="c0"><span>We&rsquo;ve</span><span>&nbsp;been discussing a number of proposals; &nbsp;they all have pros and cons. &nbsp;They all center around 3 </span><span>new</span><span>&nbsp;standard executors:</span></p><ul class="c3 lst-kix_7rtf30mrviy0-0 start"><li class="c0 c1"><span>std::thread_executor</span></li></ul><ul class="c3 lst-kix_7rtf30mrviy0-1 start"><li class="c0 c5"><span>spins up a thread for each task</span></li></ul><ul class="c3 lst-kix_7rtf30mrviy0-0"><li class="c0 c1"><span>std::</span><span>default_pool_executor</span><span>:</span></li></ul><ul class="c3 lst-kix_7rtf30mrviy0-1"><li class="c0 c5"><span>uses a thread pool, possibly from the system</span></li><li class="c0 c5"><span>generally faster than thread_per_task</span></li><li class="c0 c5"><span>may have </span><span>concurrent</span><span>&nbsp;blocked thread limitations, but should have &ldquo;enough&rdquo; threads that programmers shouldn&rsquo;t worry generally about it</span></li><li class="c0 c5"><span>has thread-local sharing</span></li><li class="c0 c5"><span>may have queueing effects</span></li></ul><ul class="c3 lst-kix_7rtf30mrviy0-0"><li class="c0 c1"><span>std::default_executor</span></li></ul><ul class="c3 lst-kix_7rtf30mrviy0-1"><li class="c0 c5"><span>defined differently in each proposal</span></li></ul><p class="c0 c2"><span></span></p><p class="c0"><span>We don&rsquo;t think any specific favorite proposal is obviously the best, but would like to hear what others think. &nbsp;Here&rsquo;s our list:</span></p><p class="c0 c2"><span></span></p><h2 class="c0 c4"><a name="h.klablog0b3in"></a><span>1. Do Nothing</span></h2><p class="c0 c2"><span></span></p><p class="c0"><span>We always have the option of not providing any default executor. &nbsp;We still provide an explicit std::thread_executor, and force users to explicitly use it. &nbsp;If they want to use the fast system thread pool they use the non portable my_system::thread_pool_executor.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>Pros:</span></p><ul class="c3 lst-kix_4p20v4bilnn5-0 start"><li class="c0 c1"><span>Easy</span><span>&nbsp;(from the standards perspective)!</span></li><li class="c0 c1"><span>Async doesn&rsquo;t change. &nbsp;(i.e. still spins up a thread)</span></li></ul><p class="c0 c2"><span></span></p><p class="c0"><span>Cons:</span></p><ul class="c3 lst-kix_cqvg0uqbqmz2-0 start"><li class="c0 c1"><span>There&rsquo;s no standardized pool executor, even though most tasks would be happiest running on the system thread pool executor.</span></li><li class="c0 c1"><span>Users will have to make a lot of executors, and the standard might need to provide an ExecutorService (like Java).</span></li><li class="c0 c1"><span>Libraries have to refer to every individual system&rsquo;s thread pool they are compatible with.</span></li></ul><p class="c0 c2"><span></span></p><p class="c0 c2"><span></span></p><h2 class="c0 c4"><a name="h.j242n2xm5ga9"></a><span>2. Provide a std::default_executor (thread per task) and std::default_pool_executor</span></h2><p class="c0 c2"><span></span></p><p class="c0"><span>We would provide all three executors in the standard, with default_executor being the same as thread_executor (except maybe allowing for thread reuse, i.e. thread-local sharing).</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>We could also rename default_pool_executor to default_fast_executor, to emphasize why you&rsquo;d use it, rather than the implementation details.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>If std::async is extended to take an executor as parameter, there&rsquo;s now a standardized easy way to use the system&rsquo;s thread pool. &nbsp;If an executor is not specified, it runs on default_executor.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>Pros:</span></p><ul class="c3 lst-kix_hov53iesit5k-0 start"><li class="c0 c1"><span>Pretty easy!</span></li><li class="c0 c1"><span>Async doesn&rsquo;t change. &nbsp;(By default it uses default_executor, i.e. spins up a thread)</span></li><li class="c0 c1"><span>Async can use the thread pool if explicitly passed</span></li><li class="c0 c1"><span>Libraries can specify they run ok on std::default_pool_executor, and can use it by default.</span></li><li class="c0 c1"><span>In practice, </span><span>implementations may offer non-conforming</span><span>&nbsp;options to use std::default_pool_executor as the default.</span></li></ul><p class="c0 c2"><span></span></p><p class="c0"><span>Cons:</span></p><ul class="c3 lst-kix_yk3snqicn2bg-0 start"><li class="c0 c1"><span>Async still defaults to thread per task</span></li><li class="c0 c1"><span>Implementations that default to using default_pool_executor are non-conforming</span></li><li class="c0 c1"><span>Different systems have different numbers of threads in their thread pool. &nbsp;Defining how those limitations affect the code has complications. &nbsp;This might involve adding a definition of &ldquo;blocked threads&rdquo; and forcing interfaces to specify when they &ldquo;block a thread&rdquo;. &nbsp;Then the user needs to count up the total number of potential blocked threads, and make sure it&rsquo;s below N &nbsp;(And what is N? &nbsp;Is it a template parameter? &ldquo;Implementation defined&rdquo;?). &nbsp;Alternately we may just say you shouldn&rsquo;t block these threads, but that limits their usefulness.</span></li></ul><ul class="c3 lst-kix_yk3snqicn2bg-1 start"><li class="c0 c5"><span>Of course in practice the user </span><span>has to worry about this today</span><span>, without the benefit of the standard explicitly specifying these constraints in a portable way.</span></li></ul><ul class="c3 lst-kix_yk3snqicn2bg-0"><li class="c0 c1"><span>There&rsquo;s two defaults&hellip; &nbsp;So which one is the real default?</span></li></ul><p class="c0 c2"><span></span></p><h2 class="c0 c4"><a name="h.iw8ffgqmsuns"></a><span>3. Provide the two new executors (thread pool &amp; thread per task), and let the user specify at compile time which should be the std::default_executor.</span></h2><p class="c0 c2"><span></span></p><p class="c0"><span>The standard doesn&rsquo;t really discuss compile time options, but we could figure out a way to allow the default executor to be selected at compile time. &nbsp;This allows an implementation to default to the system thread pool, but allows the escape valve of forcing thread-per-task if you need it.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>This comes in two varieties:</span></p><ol class="c3 lst-kix_1yicy4pz0byp-0 start" start="1"><li class="c0 c1"><span>std::async doesn&rsquo;t change, continues to create a new thread per task </span></li><li class="c0 c1"><span>std::async by default uses std::default_executor to create new tasks</span></li></ol><p class="c0 c2"><span></span></p><p class="c0"><span>Pros:</span></p><ul class="c3 lst-kix_hov53iesit5k-0"><li class="c0 c1"><span>Async can use the thread pool or thread-per-task if explicitly passed</span></li><li class="c0 c1"><span>Libraries can specify they run ok on std::default_pool_executor</span></li><li class="c0 c1"><span>In practice, implementations may now offer a </span><span class="c7">conforming </span><span>option to use std::default_pool_executor as the default.</span></li><li class="c0 c1"><span>In the distant future, other executors like fibers or GPU pools could potentially use this hook to become the default.</span></li></ul><p class="c0 c2"><span></span></p><p class="c0"><span>Cons:</span></p><ul class="c3 lst-kix_yk3snqicn2bg-0"><li class="c0 c1"><span>Under A) std::async still defaults to thread per task.</span></li><li class="c0 c1"><span>Under B) the constraints on std::async change based on a compile time flag!</span></li><li class="c0 c1"><span>If a library uses std::default_executor but can&rsquo;t run on the </span><span>default_thread_pool</span><span>&nbsp;then it&rsquo;s not safe the change the default_executor. &nbsp;See discussion above about specifying constraints. &nbsp;This is even worse under B) where libraries using async have the same issue.</span></li><li class="c0 c1"><span>Different implementations may have different default executors, making porting code more difficult. &nbsp;You&rsquo;ll have to specify your default executor, and it may not be one that performs well on every platform.</span></li></ul><p class="c0 c2"><span></span></p><p class="c0 c2"><span></span></p><h2 class="c0 c4"><a name="h.q4hxausg6qkc"></a><span>4. Add std::</span><span>default_executor</span><span>&nbsp;but with weak enough guarantees that can be implemented by a system thread pool</span></h2><p class="c0 c2"><span></span></p><p class="c0"><span>Making default_executor compatible with thread pools will strongly encourage use of system thread pools. &nbsp;We still </span><span>provide std::thread_executor as an escape valve, which will work for any existing code.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>This on also comes in two varieties:</span></p><ol class="c3 lst-kix_4uiyey1rizlr-0 start" start="1"><li class="c0 c1"><span>std::async doesn&rsquo;t change, continues to create a new thread per task</span></li><li class="c0 c1"><span>std::async by default uses std::default_executor to create new tasks</span></li></ol><p class="c0 c2"><span></span></p><p class="c0"><span>Pros:</span></p><ul class="c3 lst-kix_ckx1twpwgr4u-0 start"><li class="c0 c1"><span>Most people use the better thread pools</span></li><li class="c0 c1"><span>If A)</span></li></ul><ul class="c3 lst-kix_ckx1twpwgr4u-1 start"><li class="c0 c5"><span>std::async doesn&rsquo;t change</span></li><li class="c0 c5"><span>You can use std::async(std::default_executor) to get faster async</span></li></ul><ul class="c3 lst-kix_ckx1twpwgr4u-0"><li class="c0 c1"><span>If B)</span></li></ul><ul class="c3 lst-kix_ckx1twpwgr4u-1"><li class="c0 c5"><span>everyone gets faster async by default</span></li><li class="c0 c5"><span>You can use std::async(std::thread_executor) to get old behavior</span></li></ul><p class="c0 c2"><span></span></p><p class="c0"><span>Cons:</span></p><ul class="c3 lst-kix_eqt55ks9wn57-0 start"><li class="c0 c1"><span>We</span><span>&nbsp;need to specify these weakened guarantees on default_executor such that it is compatible with all existing system thread pools, but also useful enough to be a decent default.</span></li></ul><ul class="c3 lst-kix_eqt55ks9wn57-1 start"><li class="c0 c5"><span>The lifetime of thread locals in the executor are very loose. &nbsp;They may be destroyed at basically any time, including after statics.</span></li><li class="c0 c5"><span>It&rsquo;s only safe to block &ldquo;a few&rdquo; threads in the default executor, where we want &ldquo;a few&rdquo; to be large enough that most users don&rsquo;t have to worry</span></li></ul><ul class="c3 lst-kix_eqt55ks9wn57-0"><li class="c0 c1"><span>In practice each platform&rsquo;s default_executor will have it&rsquo;s own properties, and users will accidentally rely on those properties, making porting more difficult.</span></li><li class="c0 c1"><span>If A)</span></li></ul><ul class="c3 lst-kix_eqt55ks9wn57-1"><li class="c0 c5"><span>default </span><span>std::async is still threads</span></li></ul><ul class="c3 lst-kix_eqt55ks9wn57-0"><li class="c0 c1"><span>If B)</span></li></ul><ul class="c3 lst-kix_eqt55ks9wn57-1"><li class="c0 c5"><span>We&rsquo;re changing the behavior of std::async. &nbsp;This is a breaking change, although the fix (specify std::thread_executor) is pretty easy to change (even just as text replacement). &nbsp;The majority of users won&rsquo;t be broken though, and most will enjoy faster code.</span></li></ul><p class="c0 c2"><span></span></p><p class="c0 c2"><span></span></p><p class="c0 c2"><span></span></p><p class="c0 c2"><span></span></p><h1 class="c0 c4"><a name="h.v1zwr2thw3bv"></a><span>Conclusion</span></h1><p class="c0 c2"><span></span></p><p class="c0"><span>We think that (1) &amp; (2) are probably not great because they will tend to keep users away from the system thread pools.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>(3) is interesting, and the most flexible solution. &nbsp;It allows advanced users to run exactly the code they want, and it encourages all libraries to specify what constraints they have on executors. &nbsp;In practice most users would move to using system thread pools by default, but we don&rsquo;t break any existing code. &nbsp;It also provides a hook for other executors to come in the future. &nbsp;All that said, it introduces an &ldquo;at compile time&rdquo; concept that&rsquo;s hard to explain in standardese, and many libraries will never specify their executor constraints, which forces users to either run with thread-per-task, or run without correctness guarantees.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>(4 B) would be great, as it would move everyone to system thread pools unless they explicitly move away from it. &nbsp;Unfortunately it would add new constraints to std::async, which would change existing behavior. &nbsp;If async is being changed or replaced in the future it might make sense to use the default_executor, but doing that now would be difficult.</span></p><p class="c0 c2"><span></span></p><p class="c0"><span>(4 A) may be the most reasonable compromise. &nbsp;It makes the default executor fairly weak in guarantees, but still a good default for users who &ldquo;don&rsquo;t care&rdquo;. &nbsp;It is tricky to nail down exactly what the guarantees should be, but I suspect people who pay attention to the guarantees will prefer explicitly specifying their executor anyway. &nbsp;Unfortunately it is verbose to use the thread pool with std::async, but it doesn&rsquo;t change any existing behavior.</span></p><p class="c0 c2"><span></span></p></body></html>