{"id":105078,"date":"2021-04-12T07:00:00","date_gmt":"2021-04-12T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=105078"},"modified":"2023-10-09T10:34:59","modified_gmt":"2023-10-09T17:34:59","slug":"20210412-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20210412-00\/?p=105078","title":{"rendered":"C++ coroutines: The lifetime of objects involved in the coroutine function"},"content":{"rendered":"<p>We <a title=\"C++ coroutines: Managing the reference count of the coroutine state\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20210409-00\/?p=105065\"> finally<\/a> hooked up the last missing piece of our coroutine promise implementation. Before we can look at the tradeoffs we&#8217;ve made, let&#8217;s step back and follow the lifetime of the various objects involved in the coroutine function.<\/p>\n<p>Suppose we have a coroutine that goes like this:<\/p>\n<pre>task SomeCoroutine(Parameter p)\r\n{\r\n    Local1 l1;\r\n    co_await l1.Method();\r\n    co_return l1.Result();\r\n}\r\n<\/pre>\n<p>The coroutine state will look something like this:<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TD><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD>promise<\/TD>\n\n    \n<TD STYLE=\"margin-right: 1ex\">\n        \n<DIV STYLE=\"border: solid 1px currentcolor; border-right: none\">&nbsp;<\/DIV>\n<\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; line-height: 120%\">(you write this)<\/TD>\n<\/TR>\n<TR>\n    \n<TD>coroutine frame<\/TD>\n\n    \n<TD STYLE=\"margin-right: 1ex\">\n        \n<DIV STYLE=\"border: solid 1px currentcolor; border-right: none\">&nbsp;<BR>\n&nbsp;<BR>\n&nbsp;<\/DIV>\n<\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; line-height: 120%\"><TT>Parameter p<\/TT><BR>\n<CODE>Local l1<\/CODE><BR>\ntemporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td>promise<\/td>\n<td style=\"margin-right: 1ex;\">\n<div style=\"border: solid 1px currentcolor; border-right: none;\">\u00a0<\/div>\n<\/td>\n<td style=\"border: solid 1px currentcolor; line-height: 120%;\">(you write this)<\/td>\n<\/tr>\n<tr>\n<td rowspan=\"3\">coroutine frame<\/td>\n<td style=\"margin-right: 1ex;\" rowspan=\"3\">\n<div style=\"border: solid 1px currentcolor; border-right: none;\">\u00a0<br \/>\n\u00a0<br \/>\n\u00a0<br \/>\n\u00a0<\/div>\n<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-style: none solid;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The coroutine state consists of three parts: Compiler-defined bookkeeping to keep track of the progress of the coroutine, the promise object (which you define), and the frame (which contains the parameters, locals, and any temporaries).<\/p>\n<p>We&#8217;ve written two kinds of promises, and they look like this:<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD>&rarr;<\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none\"><TT>Parameter p<\/TT><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none\"><TT>Parameter p<\/TT><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><tt>shared_ptr<\/tt><\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\"><tt>ReturnValue<\/tt><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid;\"><tt>ReturnValue<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-style: none solid;\"><tt>Local l1<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The first kind is the simple one, where the promise object is a <code>shared_<wbr \/>ptr<\/code> to a <code>result_<wbr \/>holder<\/code> object, and the <code>result_<wbr \/>holder<\/code> holds the return value and other internal bookkeeping. In the first kind of promise, there are two allocations, one for the coroutine state, and one for the <code>result_<wbr \/>holder<\/code>.<\/p>\n<p>The second kind is the one where we inlined the <code>result_<wbr \/>holder<\/code> object into the promise. In the second kind of promise, there is just one allocation, namely for the coroutine state. The promises consists of the <code>result_<wbr \/>holder<\/code> itself, so there is no second allocation.<\/p>\n<p>Let&#8217;s track the memory usage and object lifetimes.<\/p>\n<p>When you call the coroutine, the first thing that happens it that the compiler allocates a coroutine state and sets up some bookkeeping. In the diagrams, boxes with heavy solid lines contain live data, whereas boxes with thin lines represent uninitialized memory. Solid lines delimit allocated memory, and dotted lines go around memory that has not yet been allocated.<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; opacity: .5\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD STYLE=\"opacity: .5\">&#x290d;<\/TD>\n\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; opacity: .5\"><TT>Parameter p<\/TT><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; opacity: .5\"><TT>Parameter p<\/TT><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; opacity: .5;\"><tt>shared_ptr<\/tt><\/td>\n<td style=\"opacity: .5;\">\u290d<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5;\"><tt>ReturnValue<\/tt><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>ReturnValue<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none; opacity: .5;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none; opacity: .5;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>At the start of the coroutine, the compiler allocates the coroutine state, but only the compiler bookkeeping portion is live. The promise and the frame remain still uninitialized.<\/p>\n<p>Next, the parameters are moved into the coroutine frame. If a parameter is a reference, then the reference is moved into the frame as a reference. In our example, this means that <code>Parameter<\/code> is constructed.<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; opacity: .5\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD STYLE=\"opacity: .5\">&#x290d;<\/TD>\n\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><CODE>Parameter<\/CODE><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><CODE>Parameter<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; opacity: .5;\"><tt>shared_ptr<\/tt><\/td>\n<td style=\"opacity: .5;\">\u290d<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5;\"><tt>ReturnValue<\/tt><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>ReturnValue<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>At this point, the coroutine bookkeeping and the <code>Parameter<\/code> in the coroutine state have been initialized.<\/p>\n<p>Next, the compiler constructs the promise object. In our first example, the constructor for the promise object also constructs the <code>shared_ptr<\/code>, which creates the promise state object that holds space for the <code>Return\u00adValue<\/code> as well as other promise bookkeeping. In our second example, the promise state is inlined into the promise. Again, memory is reserved for the <code>Return\u00adValue<\/code>, but nothing is in it yet.<\/p>\n<p>This is what we have so far:<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD>&rarr;<\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; opacity: .5\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\"><code>shared_ptr<\/code><\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none; opacity: .5;\"><code>ReturnValue<\/code><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><code>ReturnValue<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 3px currentcolor;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><code>Local l1<\/code><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><code>Local l1<\/code><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In the first example, the <code>shared_<wbr \/>ptr<\/code> for the promise object has been initialized, and it points to a newly-allocated <code>result_<wbr \/>holder<\/code>. In that <code>result_<wbr \/>holder<\/code>, the bookkeeping is initialized, but the return value portion remains uninitialized. The return value won&#8217;t get initialized until the coroutine exits either by reaching a <code>co_return<\/code> or by exiting with an exception.<\/p>\n<p>In the second example, the promise object is itself just a <code>result_<wbr \/>holder<\/code>; there is no <code>shared_<wbr \/>ptr<\/code> and no second allocation. Again, the bookkeeping for the <code>result_<wbr \/>holder<\/code> has been initialized, but the portion that holds the return value won&#8217;t get initialized until there is something to return.<\/p>\n<p>As the coroutine runs, local variables and temporaries are constructed and destructed according to the usual rules of the C++ language. Those local variables and temporaries appear and disappear in the frame. In our example, this means that <code>Local<\/code> gets constructed in the frame, and then a temporary is created to hold the return value from <code>l1.Method()<\/code>. We then go through the standard <code>co_await<\/code> machinery: From that temporary value, we obtain an awaiter, which is another temporary value, which also goes into the frame. The awaiter arranges for the coroutine to resume, and at the resumption, the temporaries are destructed.<\/p>\n<p>Just before the <code>co_return<\/code>, we have this:<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD>&rarr;<\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; opacity: .5\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\"><tt>shared_ptr<\/tt><\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none; opacity: .5;\"><tt>ReturnValue<\/tt><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>ReturnValue<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 3px currentcolor;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor; border-top: none;\"><tt>Local l1<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; opacity: .5;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In both versions of the coroutine state, the compiler bookkeeping remains initialized, as well as the bookkeeping for the <code>result_<wbr \/>holder<\/code>, the captured parameter, and the local variable. In the first example, we also have a <code>shared_<wbr \/>ptr<\/code> to the <code>result_<wbr \/>holder<\/code>, but in the second example, <code>result_<wbr \/>holder<\/code> is embedded in the coroutine state, so no pointer or second allocation is required. In the frame, the parameter remains initialized as well as the local. The temporary is now uninitialized because the lifetime of the temporary has ended.<\/p>\n<p>We now reach the <code>co_return<\/code>. The <code>co_return<\/code>&#8216;d value is Let&#8217;s say that the <code>Result()<\/code> method returns a <code>Return\u00adValue<\/code> object by value. That rvalue reference to the <code>Return\u00adValue<\/code> is passed to the promise&#8217;s <code>return_<wbr \/>value<\/code> method. In our first example, the promise move-constructs the <code>Return\u00adValue<\/code> in the external promise state. In our second example, the promise move-constructs it in the embedded promise state.<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD>&rarr;<\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\"><tt>shared_ptr<\/tt><\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>ReturnValue<\/tt><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>ReturnValue<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor; border-top: none;\"><tt>Local l1<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>At this point, the <code>Return\u00adValue<\/code> object in the <code>result_<wbr \/>holder<\/code> is initialized. In the first example, the <code>result_<wbr \/>holder<\/code> is external to the coroutine state; in the second example, it is embedded inside the coroutine state.<\/p>\n<p>At the end of the <code>co_return<\/code> statement, the temporary <code>Return\u00adValue<\/code> is destructed. This <code>Return\u00adValue<\/code> does not have a lifetime that extends across a suspension point, so it doesn&#8217;t have to go into the coroutine frame. It can just go on the regular stack.<\/p>\n<p>The coroutine now completes, and any remaining local variables are destructed. In this case, it means that the <code>Local<\/code> in the coroutine frame is now destructed. The coroutine frame now consists only of the compiler bookkeeping, the promise, and the parameters. All of the locals and temporaries have been destructed. The memory for them is just sitting around unused.<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD>&rarr;<\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\"><tt>shared_ptr<\/tt><\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>ReturnValue<\/tt><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>ReturnValue<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 3px currentcolor;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The code paths diverge significally when the coroutine completes. In our first version, our <code>final_<wbr \/>suspend<\/code> allows the coroutine state to be destroyed. Destroying the coroutine state destructs the promise, then the parameters, then the bookkeeping, following the usual C++ rule of destructing in reverse order of construction.<\/p>\n<p>In our second version, our <code>final_<wbr \/>suspend<\/code> keeps the coroutine state alive because the caller has a reference to it via the task. The objects now look like this:<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH STYLE=\"opacity: .5\">Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; opacity: .5\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; opacity: .5\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD STYLE=\"opacity: .5\">&#x290d;<\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5\"><TT>Parameter p<\/TT><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th style=\"opacity: .5;\">Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; opacity: .5;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; opacity: .5;\"><tt>shared_ptr<\/tt><\/td>\n<td style=\"opacity: .5;\">\u290d<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>ReturnValue<\/tt><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>ReturnValue<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In the first version, the entire coroutine state has been destroyed and deallocated, leaving only the <code>result_<wbr \/>holder<\/code> with the <code>Return\u00adValue<\/code> and a little bit of result holder bookkeeping. But in the second version, the coroutine state is still allocated, with live compiler bookkeeping, a live promise, and the live captured parameter. The live compiler bookeeping says &#8220;This coroutine has suspended at its <code>final_<wbr \/>suspend<\/code>. If you resume the coroutine, it will self-destruct.&#8221;<\/p>\n<p>In both cases, the <code>result_<wbr \/>holder<\/code> (either external or embedded) is kept alive by the <code>task<\/code> that we returned to our caller.<\/p>\n<p>The caller&#8217;s <code>co_await<\/code> copies (in the first case) or moves (in the second case) the result out of the <code>Return\u00adValue<\/code>.<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH STYLE=\"opacity: .5\">Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; opacity: .5\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; opacity: .5\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD STYLE=\"opacity: .5\">&#x290d;<\/TD>\n\n    \n<TD STYLE=\"border: solid 3px currentcolor; border-bottom: none\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5\"><TT>Parameter p<\/TT><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: solid 3px currentcolor; border-top: none\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"See descriptive text\">\n<TR>\n    \n<TH>Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 3px currentcolor\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\">(<CODE>ReturnValue<\/CODE>)<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; background-color: #bbebff\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-bottom: none; background-color: #bbebff\"><TT>Parameter p<\/TT><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: solid 1px currentcolor; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th style=\"opacity: .5;\">Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th>Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; opacity: .5;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; opacity: .5;\"><tt>shared_ptr<\/tt><\/td>\n<td style=\"opacity: .5;\">\u290d<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\"><tt>ReturnValue<\/tt><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-bottom: none;\">(<tt>ReturnValue<\/tt>)<\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor; border-top: none;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 3px currentcolor;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-style: none solid; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none; opacity: .5;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>There is no change to the first version of our coroutine implementation, because copying the <code>Return\u00adValue<\/code> doesn&#8217;t modify the original. But in the second version, moving the <code>Return\u00adValue<\/code> to the caller causes the <code>Return\u00adValue<\/code> inside the embedded <code>result_<wbr \/>holder<\/code> to become empty. It is still initialized, but it holds nothing of interest.<\/p>\n<p>And finally, the caller destructs the task, which causes the last bit to disappear. In the first case, the shared promise state destructs, which means that the result holder bookkeeping and <code>Return\u00adValue<\/code> both destruct, and then the memory for the <code>result_<wbr \/>holder<\/code> is freed. In the second case, we go through coroutine state destruction, which as we noted earlier destructs the coroutine state destructs the promise, then the parameters, then the bookkeeping.<\/p>\n<p><!--\n\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block; margin-right: 2em\"\n    TITLE=\"Everything is destructed and freed\">\n<TR>\n    \n<TH STYLE=\"opacity: .5\">Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; opacity: .5\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; opacity: .5\"><CODE>shared_ptr<\/CODE><\/TD>\n\n    \n<TD STYLE=\"opacity: .5\">&#x290d;<\/TD>\n\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5\"><CODE>ReturnValue<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5\"><TT>Parameter p<\/TT><\/TD>\n\n    \n<TD><\/TD>\n\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n<TABLE BORDER=0 CLASS=\"cp3\" CELLSPACING=0 CELLPADDING=3\n    STYLE=\"border-collapse: collapse; text-align: center; display: inline-block\"\n    TITLE=\"Everything is destructed and freed\">\n<TR>\n    \n<TH STYLE=\"opacity: .5\">Coroutine state<\/TH>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; opacity: .5\">bookkeeping<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5\">(<CODE>ReturnValue<\/CODE>)<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5\">other stuff<\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5\"><TT>Parameter p<\/TT><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5\"><CODE>Local l1<\/CODE><\/TD>\n<\/TR>\n<TR>\n    \n<TD STYLE=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5\">temporaries<\/TD>\n<\/TR>\n<\/TABLE>\n\n--><\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" title=\"See descriptive text\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th style=\"opacity: .5;\">Coroutine state<\/th>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<th style=\"opacity: .5;\">Coroutine state<\/th>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; opacity: .5;\">bookkeeping<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: dotted 1px #c0c0c0; opacity: .5;\">bookkeeping<\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; opacity: .5;\"><tt>shared_ptr<\/tt><\/td>\n<td style=\"opacity: .5;\">\u290d<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5;\"><tt>ReturnValue<\/tt><\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5;\">(<tt>ReturnValue<\/tt>)<\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5;\"><tt>Parameter p<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5;\">other stuff<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5;\">other stuff<\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-bottom: none; opacity: .5;\"><tt>Parameter p<\/tt><\/td>\n<\/tr>\n<tr>\n<td style=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5;\">temporaries<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-style: none dotted; opacity: .5;\"><tt>Local l1<\/tt><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"border: dotted 1px #c0c0c0; border-top: none; opacity: .5;\">temporaries<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Next time, we&#8217;ll compare the two designs and identify pros and cons.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Follow them as they pop into existence and vanish.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-105078","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Follow them as they pop into existence and vanish.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105078","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=105078"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105078\/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=105078"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=105078"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=105078"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}