Topic: Regarding Futures and Executors (n3784 and n3785)
Author: matthias.einwag@googlemail.com
Date: Tue, 3 Jun 2014 12:34:05 -0700 (PDT)
Raw View
------=_Part_3818_32027013.1401824045155
Content-Type: text/plain; charset=UTF-8
Hi everyone,
I started implementing parts of these proposals in order to build an async
IO library on top of it.
I really love the idea and all the possibilites it provides.
However during the implementation a few questions and issues came up, that
I would like to present here:
- The future member function is_ready() is also called only ready() on page
12.
- Regarding deferred futures the paper states: "If the parent has a policy
of launch::deferred and the continuation does not have a specified launch
policy or scheduler, then the parent is filled by immediately calling
..wait() , and the policy of the antecedent is launch::deferred". I think
for deferred futures the future has to be always waited upon in the moment
when a continuation is attached. Otherwise async or executor-scheduled
continuations would never launch. But maybe this is meant and only deferred
futures are mentioned here because for them waiting on the inner result
could be optional and also be deferred.
- make_ready_future can construct a ready future which is completed with a
given value. But it should also be possible to construct one which is
completed with an exception.
- future.unwrap():
- What happens when the future<future<T>> to unwrap has no associated
state? This could either throw an exception or return a default constructed
future<T> (which also has no state).
- Should the unwrapped future inherit the properties (launch policy,
executor) or the outer or inner future? As far as I can tell from my
implementation it can also inherit it from the outer future, because the
inner future is not guaranteed to exist at the point of the unwrapped
future's construction.
- Beeing able to check for an exception in a future an extracting it
without throwing would be helpful.
- I would like to have the ability to already set an executor (or maybe
also launch policy) as a constructor argument for the promise. This would
set the default executor for the associated promise. And if a continuation
gets attached with promise.get_future().then(func) it would be
automatically scheduled on this scheduler, without requiring the user to
explicetly specify the executor as a .then parameter.
- I think the ability to retrieve the active executor of a running thread
would also be helpful, like std::executor*
std::this_executor::get_executor(). The active executor would have to be
stored in thread local storage. This function can for example be used to
easily run continuations on the same thread were the initial API call that
returned a future was made. E.g. when you call
file.read(1024bytes).then(...) inside the event loop of an UI framework the
read function could automatically set the default continuation executor to
the current thread's executor and the user can again avoid to explicetly
specify it. It would also help to check that some calls can only be made in
specific functions/executors. E.g. in my IO library I currently have an
executor which runs around an epoll instance (could also be IOCP queue) -
and only inside this executor you are allowed to to IO calls. Besides that
it could also be used for deadlock detection: If the promise get's told
through the constructor that will be completed from inside a special
executor then future<T>::get/wait() could throw an exception when anyone
tries to fetch the value from exactly that executor. However getting the
current executor might be a little bit tricky if executors are nested, like
with the proposed serial_executor. It would either refer only to the most
inner executor, or some kind of executor stack / linked-list, or a
executor::get_parent() function would be needed.
Best regards
Matthias
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3818_32027013.1401824045155
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi everyone,<br><br>I started implementing parts of these =
proposals in order to build an async IO library on top of it.<br>I really l=
ove the idea and all the possibilites it provides.<br>However during the im=
plementation a few questions and issues came up, that I would like to prese=
nt here:<br><br>- The future member function is_ready() is also called only=
ready() on page 12.<br>- Regarding deferred futures the paper states: "If =
the parent has a policy of launch::deferred and the continuation does not h=
ave a specified launch policy or scheduler, then the parent is filled by im=
mediately calling .wait() , and the policy of the antecedent is launch::def=
erred". I think for deferred futures the future has to be always waited upo=
n in the moment when a continuation is attached. Otherwise async or executo=
r-scheduled continuations would never launch. But maybe this is meant and o=
nly deferred futures are mentioned here because for them waiting on the inn=
er result could be optional and also be deferred.<br>- make_ready_future ca=
n construct a ready future which is completed with a given value. But it sh=
ould also be possible to construct one which is completed with an exception=
..<br>- future.unwrap(): <br> - What happens when the future<=
;future<T>> to unwrap has no associated state? This could either t=
hrow an exception or return a default constructed future<T> (which al=
so has no state).<br> - Should the unwrapped future inherit th=
e properties (launch policy, executor) or the outer or inner future? As far=
as I can tell from my implementation it can also inherit it from the outer=
future, because the inner future is not guaranteed to exist at the point o=
f the unwrapped future's construction.<br>- Beeing able to check for an exc=
eption in a future an extracting it without throwing would be helpful.<br>-=
I would like to have the ability to already set an executor (or maybe also=
launch policy) as a constructor argument for the promise. This would set t=
he default executor for the associated promise. And if a continuation gets =
attached with promise.get_future().then(func) it would be automatically sch=
eduled on this scheduler, without requiring the user to explicetly specify =
the executor as a .then parameter.<br>- I think the ability to retrieve the=
active executor of a running thread would also be helpful, like std::execu=
tor* std::this_executor::get_executor(). The active executor would have to =
be stored in thread local storage. This function can for example be used to=
easily run continuations on the same thread were the initial API call that=
returned a future was made. E.g. when you call file.read(1024bytes).then(.=
...) inside the event loop of an UI framework the read function could automa=
tically set the default continuation executor to the current thread's execu=
tor and the user can again avoid to explicetly specify it. It would also he=
lp to check that some calls can only be made in specific functions/executor=
s. E.g. in my IO library I currently have an executor which runs around an =
epoll instance (could also be IOCP queue) - and only inside this exec=
utor you are allowed to to IO calls. Besides that it could also be used for=
deadlock detection: If the promise get's told through the constructor that=
will be completed from inside a special executor then future<T>::get=
/wait() could throw an exception when anyone tries to fetch the value from =
exactly that executor. However getting the current executor might be a litt=
le bit tricky if executors are nested, like with the proposed serial_execut=
or. It would either refer only to the most inner executor, or some kind of =
executor stack / linked-list, or a executor::get_parent() function would be=
needed.<br><br>Best regards<br>Matthias<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3818_32027013.1401824045155--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Sun, 26 Oct 2014 07:14:56 -0700 (PDT)
Raw View
------=_Part_2521_2016409101.1414332896423
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Le mardi 3 juin 2014 21:34:05 UTC+2, matthia...@googlemail.com a =C3=A9crit=
:
>
> Hi everyone,
>
> I started implementing parts of these proposals in order to build an asyn=
c=20
> IO library on top of it.
> I really love the idea and all the possibilites it provides.
> However during the implementation a few questions and issues came up, tha=
t=20
> I would like to present here:
>
> - The future member function is_ready() is also called only ready() on=20
> page 12.
>
I think this is fixed now.=20
> - Regarding deferred futures the paper states: "If the parent has a polic=
y=20
> of launch::deferred and the continuation does not have a specified launch=
=20
> policy or scheduler, then the parent is filled by immediately calling=20
> .wait() , and the policy of the antecedent is launch::deferred". I think=
=20
> for deferred futures the future has to be always waited upon in the momen=
t=20
> when a continuation is attached. Otherwise async or executor-scheduled=20
> continuations would never launch. But maybe this is meant and only deferr=
ed=20
> futures are mentioned here because for them waiting on the inner result=
=20
> could be optional and also be deferred.
>
There have been quite a lot of changes respect to deferred futures. Please,=
=20
could you see if there is still an issue?=20
> - make_ready_future can construct a ready future which is completed with =
a=20
> given value. But it should also be possible to construct one which is=20
> completed with an exception.
>
We have added make_exceptional_future.=20
> - future.unwrap():=20
>
unwrap has been removed.=20
> - What happens when the future<future<T>> to unwrap has no associated=
=20
> state? This could either throw an exception or return a default construct=
ed=20
> future<T> (which also has no state).
>
I think that this has been fixed. When the future is invalid an exception=
=20
is set.
> - Should the unwrapped future inherit the properties (launch policy,=
=20
> executor) or the outer or inner future? As far as I can tell from my=20
> implementation it can also inherit it from the outer future, because the=
=20
> inner future is not guaranteed to exist at the point of the unwrapped=20
> future's construction.
>
This point has not been discussed. Please could you open an issue at=20
https://github.com/cplusplus/concurrency_ts/issues.=20
> - Beeing able to check for an exception in a future an extracting it=20
> without throwing would be helpful.
>
n4048 has proposed a exception_ptr_cast (get_exception_ptr) but this has=20
not been retained yet. =20
- I would like to have the ability to already set an executor (or maybe=20
> also launch policy) as a constructor argument for the promise. This would=
=20
> set the default executor for the associated promise. And if a continuatio=
n=20
> gets attached with promise.get_future().then(func) it would be=20
> automatically scheduled on this scheduler, without requiring the user to=
=20
> explicetly specify the executor as a .then parameter.
>
While this could be convenient, it would make all the promise more=20
expensive and needs a type erased executor.
- I think the ability to retrieve the active executor of a running thread=
=20
> would also be helpful, like std::executor*=20
> std::this_executor::get_executor(). The active executor would have to be=
=20
> stored in thread local storage. This function can for example be used to=
=20
> easily run continuations on the same thread were the initial API call tha=
t=20
> returned a future was made. E.g. when you call=20
> file.read(1024bytes).then(...) inside the event loop of an UI framework t=
he=20
> read function could automatically set the default continuation executor t=
o=20
> the current thread's executor and the user can again avoid to explicetly=
=20
> specify it. It would also help to check that some calls can only be made =
in=20
> specific functions/executors.=20
>
In Boost.Thread I have added a hook to be run at the entry of a thread of=
=20
an thread_pool. This entry can easily set a thread local variable usable by=
=20
all the functions.
template <class AtThreadEntry>
basic_thread_pool( unsigned const thread_count, AtThreadEntry at_thread=
_entry);
At thread entry=20
It is common idiom to set some thread local variable at the beginning of a=
=20
thread. As Executors could instantiate threads internally these Executors=
=20
shall have the ability to call a user specific function at thread entry on=
=20
the executor constructor.=20
For executors that don't instantiate any thread and that would use the=20
current thread this function shall be called only for the thread calling=20
the at_thread_entry member function.=20
Current executor=20
The library does not provision for the ability to get the current executor,=
=20
though having access to it could simplify a lot the user code.=20
The reason is that the user can always use a thread_local variable and=20
reset it using the at_thread_entry member function.=20
thread_local current_executor_state_type current_executor_state;executor* c=
urrent_executor() { return current_executor_state.current_executor(); }basi=
c_thread_pool pool(
// at_thread_entry
[](basic_thread_pool& pool) {
current_executor_state.set_current_executor(pool);
});
Default executor=20
The library authors share some of the concerns of the C++ standard=20
committee (introduction of a new single shared resource, a singleton, could=
=20
make it difficult to make it portable to all the environments) and that=20
this library doesn't need to provide a default executor for the time been.=
=20
The user can always define his default executor himself and use the=20
at_thread_entry member function to set the default constructor.=20
thread_local default_executor_state_type default_executor_state;executor* d=
efault_executor() { return default_executor_state.default_executor(); }
// in mainMyDefaultExecutor myDefaultExecutor(
// at_thread_entry
[](MyDefaultExecutor& ex) {
default_executor_state.set_default_executor(ex);
});
basic_thread_pool pool(
// at_thread_entry
[&myDefaultExecutor](basic_thread_pool& pool) {
default_executor_state.set_default_executor(myDefaultExecutor);
});
=20
> E.g. in my IO library I currently have an executor which runs around an=
=20
> epoll instance (could also be IOCP queue) - and only inside this executo=
r=20
> you are allowed to to IO calls. Besides that it could also be used for=20
> deadlock detection: If the promise get's told through the constructor tha=
t=20
> will be completed from inside a special executor then future<T>::get/wait=
()=20
> could throw an exception when anyone tries to fetch the value from exactl=
y=20
> that executor.=20
>
=20
> However getting the current executor might be a little bit tricky if=20
> executors are nested, like with the proposed serial_executor. It would=20
> either refer only to the most inner executor, or some kind of executor=20
> stack / linked-list, or a executor::get_parent() function would be needed=
..
>
> Even if Executors can be nested, I don't see how a thread can run on two=
=20
executors. Could you elaborate?
Vicente
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2521_2016409101.1414332896423
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mardi 3 juin 2014 21:34:05 UTC+2, matthia...@go=
oglemail.com a =C3=A9crit :<blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
"><div dir=3D"ltr">Hi everyone,<br><br>I started implementing parts of thes=
e proposals in order to build an async IO library on top of it.<br>I really=
love the idea and all the possibilites it provides.<br>However during the =
implementation a few questions and issues came up, that I would like to pre=
sent here:<br><br>- The future member function is_ready() is also called on=
ly ready() on page 12.<br></div></blockquote><div>I think this is fixed now=
.. <br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">-=
Regarding deferred futures the paper states: "If the parent has a policy o=
f launch::deferred and the continuation does not have a specified launch po=
licy or scheduler, then the parent is filled by immediately calling .wait()=
, and the policy of the antecedent is launch::deferred". I think for defer=
red futures the future has to be always waited upon in the moment when a co=
ntinuation is attached. Otherwise async or executor-scheduled continuations=
would never launch. But maybe this is meant and only deferred futures are =
mentioned here because for them waiting on the inner result could be option=
al and also be deferred.<br></div></blockquote><div>There have been quite a=
lot of changes respect to deferred futures. Please, could you see if there=
is still an issue? <br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div dir=3D"ltr">- make_ready_future can construct a ready future which is =
completed with a given value. But it should also be possible to construct o=
ne which is completed with an exception.<br></div></blockquote><div>We have=
added make_exceptional_future. <br></div><blockquote class=3D"gmail_quote"=
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-=
left: 1ex;"><div dir=3D"ltr">- future.unwrap(): <br></div></blockquote><div=
>unwrap has been removed. <br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"> - What happens when the future<futu=
re<T>> to unwrap has no associated state? This could either throw =
an exception or return a default constructed future<T> (which also ha=
s no state).<br></div></blockquote><div>I think that this has been fixed. W=
hen the future is invalid an exception is set.<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"> - Should the unw=
rapped future inherit the properties (launch policy, executor) or the outer=
or inner future? As far as I can tell from my implementation it can also i=
nherit it from the outer future, because the inner future is not guaranteed=
to exist at the point of the unwrapped future's construction.<br></div></b=
lockquote><div>This point has not been discussed. Please could you open an =
issue at https://github.com/cplusplus/concurrency_ts/issues. <br></div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">- Beeing able to =
check for an exception in a future an extracting it without throwing would =
be helpful.<br></div></blockquote><div>n4048 has proposed a exception_ptr_c=
ast (get_exception_ptr) but this has not been retained yet. <br><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">- I woul=
d like to have the ability to already set an executor (or maybe also launch=
policy) as a constructor argument for the promise. This would set the defa=
ult executor for the associated promise. And if a continuation gets attache=
d with promise.get_future().then(<wbr>func) it would be automatically sched=
uled on this scheduler, without requiring the user to explicetly specify th=
e executor as a .then parameter.<br></div></blockquote><div><br>While this =
could be convenient, it would make all the promise more expensive and needs=
a type erased executor.<br><br></div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr">- I think the ability to retrieve the active execu=
tor of a running thread would also be helpful, like std::executor* std::thi=
s_executor::get_<wbr>executor(). The active executor would have to be store=
d in thread local storage. This function can for example be used to easily =
run continuations on the same thread were the initial API call that returne=
d a future was made. E.g. when you call file.read(1024bytes).then(...) insi=
de the event loop of an UI framework the read function could automatically =
set the default continuation executor to the current thread's executor and =
the user can again avoid to explicetly specify it. It would also help to ch=
eck that some calls can only be made in specific functions/executors. </div=
></blockquote><div><br>In Boost.Thread I have added a hook to be run =
at the entry of a thread of an thread_pool. This entry can easily set a thr=
ead local variable usable by all the functions.<br><br><pre class=3D"progra=
mlisting"> <span class=3D"keyword">template</span> <span class=3D"specia=
l"><</span><span class=3D"keyword">class</span> <span class=3D"identifie=
r">AtThreadEntry</span><span class=3D"special">></span>
<span class=3D"identifier">basic_thread_pool</span><span class=3D"speci=
al">(</span> <span class=3D"keyword">unsigned</span> <span class=3D"keyword=
">const</span> <span class=3D"identifier">thread_count</span><span class=3D=
"special">,</span> <span class=3D"identifier">AtThreadEntry</span> <span cl=
ass=3D"identifier">at_thread_entry</span><span class=3D"special">);</span><=
/pre><br><h6><a class=3D"link">At
thread entry</a>
</h6>
<p>
It is common idiom to set some thread local variable at the begin=
ning of
a thread. As Executors could instantiate threads internally these=
Executors
shall have the ability to call a user specific function at thread=
entry
on the executor constructor.
</p>
<p>
For executors that don't instantiate any thread and that would us=
e the
current thread this function shall be called only for the thread =
calling
the <code class=3D"computeroutput"><span class=3D"identifier">at_=
thread_entry</span></code> member
function.
</p>
<h6>
<a name=3D"thread.synchronization.executors.rationale.h3"></a>
<span><a name=3D"thread.synchronization.executors.rationale.cance=
lation"></a></span><a class=3D"link">Current
executor</a>
</h6>
<p>
The library does not provision for the ability to get the current=
executor,
though having access to it could simplify a lot the user code.
</p>
<p>
The reason is that the user can always use a thread_local variabl=
e and
reset it using the <code class=3D"computeroutput"><span class=3D"=
identifier">at_thread_entry</span>
</code> member function.
</p>
<pre class=3D"programlisting"><span class=3D"keyword">thread_local</span> <=
span class=3D"identifier">current_executor_state_type</span> <span class=3D=
"identifier">current_executor_state</span><span class=3D"special">;</span>
<span class=3D"identifier">executor</span><span class=3D"special">*</span> =
<span class=3D"identifier">current_executor</span><span class=3D"special">(=
)</span> <span class=3D"special">{</span> <span class=3D"keyword">return</s=
pan> <span class=3D"identifier">current_executor_state</span><span class=3D=
"special">.</span><span class=3D"identifier">current_executor</span><span c=
lass=3D"special">();</span> <span class=3D"special">}</span>
<span class=3D"identifier">basic_thread_pool</span> <span class=3D"identifi=
er">pool</span><span class=3D"special">(</span>
<span class=3D"comment">// at_thread_entry</span>
<span class=3D"special">[](</span><span class=3D"identifier">basic_thread_=
pool</span><span class=3D"special">&</span> <span class=3D"identifier">=
pool</span><span class=3D"special">)</span> <span class=3D"special">{</span=
>
<span class=3D"identifier">current_executor_state</span><span class=3D"sp=
ecial">.</span><span class=3D"identifier">set_current_executor</span><span =
class=3D"special">(</span><span class=3D"identifier">pool</span><span class=
=3D"special">);</span>
<span class=3D"special">}</span>
<span class=3D"special">);</span>
</pre>
<h6>
<a name=3D"thread.synchronization.executors.rationale.h5"></a> <span><=
/span><a class=3D"link">Default
executor</a>
</h6>
<p>
The library authors share some of the concerns of the C++ standar=
d committee
(introduction of a new single shared resource, a singleton, could=
make
it difficult to make it portable to all the environments) and tha=
t this
library doesn't need to provide a default executor for the time b=
een.
</p>
<p>
The user can always define his default executor himself and use t=
he <code class=3D"computeroutput"><span class=3D"identifier">at_thread_entr=
y</span> </code> member function to set
the default constructor.
</p>
<pre class=3D"programlisting"><span class=3D"keyword">thread_local</span> <=
span class=3D"identifier">default_executor_state_type</span> <span class=3D=
"identifier">default_executor_state</span><span class=3D"special">;</span>
<span class=3D"identifier">executor</span><span class=3D"special">*</span> =
<span class=3D"identifier">default_executor</span><span class=3D"special">(=
)</span> <span class=3D"special">{</span> <span class=3D"keyword">return</s=
pan> <span class=3D"identifier">default_executor_state</span><span class=3D=
"special">.</span><span class=3D"identifier">default_executor</span><span c=
lass=3D"special">();</span> <span class=3D"special">}</span>
<span class=3D"comment">// in main</span>
<span class=3D"identifier">MyDefaultExecutor</span> <span class=3D"identifi=
er">myDefaultExecutor</span><span class=3D"special">(</span>
<span class=3D"comment">// at_thread_entry</span>
<span class=3D"special">[](</span><span class=3D"identifier">MyDefaultExec=
utor</span><span class=3D"special">&</span> <span class=3D"identifier">=
ex</span><span class=3D"special">)</span> <span class=3D"special">{</span>
<span class=3D"identifier">default_executor_state</span><span class=3D"sp=
ecial">.</span><span class=3D"identifier">set_default_executor</span><span =
class=3D"special">(</span><span class=3D"identifier">ex</span><span class=
=3D"special">);</span>
<span class=3D"special">}</span>
<span class=3D"special">);</span>
<span class=3D"identifier">basic_thread_pool</span> <span class=3D"identifi=
er">pool</span><span class=3D"special">(</span>
<span class=3D"comment">// at_thread_entry</span>
<span class=3D"special">[&</span><span class=3D"identifier">myDefaultE=
xecutor</span><span class=3D"special">](</span><span class=3D"identifier">b=
asic_thread_pool</span><span class=3D"special">&</span> <span class=3D"=
identifier">pool</span><span class=3D"special">)</span> <span class=3D"spec=
ial">{</span>
<span class=3D"identifier">default_executor_state</span><span class=3D"sp=
ecial">.</span><span class=3D"identifier">set_default_executor</span><span =
class=3D"special">(</span><span class=3D"identifier">myDefaultExecutor</spa=
n><span class=3D"special">);</span>
<span class=3D"special">}</span>
<span class=3D"special">);</span>
</pre><br> <br></div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
dir=3D"ltr">E.g. in my IO library I currently have an executor which runs =
around an epoll instance (could also be IOCP queue) - and only inside=
this executor you are allowed to to IO calls. Besides that it could also b=
e used for deadlock detection: If the promise get's told through the constr=
uctor that will be completed from inside a special executor then future<=
T>::get/wait() could throw an exception when anyone tries to fetch the v=
alue from exactly that executor. </div></blockquote><div> </div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">However getting the=
current executor might be a little bit tricky if executors are nested, lik=
e with the proposed serial_executor. It would either refer only to the most=
inner executor, or some kind of executor stack / linked-list, or a executo=
r::get_parent() function would be needed.<br><br></div></blockquote><div>Ev=
en if Executors can be nested, I don't see how a thread can run on two exec=
utors. Could you elaborate?<br><br>Vicente<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2521_2016409101.1414332896423--
.
Author: matthias.einwag@googlemail.com
Date: Sun, 26 Oct 2014 12:49:37 -0700 (PDT)
Raw View
------=_Part_351_1437244875.1414352977447
Content-Type: text/plain; charset=UTF-8
Hi, thanks for the answer,
my comments are below
Best regards
Matthias
> Hi everyone,
>>
>> I started implementing parts of these proposals in order to build an
>> async IO library on top of it.
>> I really love the idea and all the possibilites it provides.
>> However during the implementation a few questions and issues came up,
>> that I would like to present here:
>>
>> - The future member function is_ready() is also called only ready() on
>> page 12.
>>
> I think this is fixed now.
>
>> - Regarding deferred futures the paper states: "If the parent has a
>> policy of launch::deferred and the continuation does not have a specified
>> launch policy or scheduler, then the parent is filled by immediately
>> calling .wait() , and the policy of the antecedent is launch::deferred". I
>> think for deferred futures the future has to be always waited upon in the
>> moment when a continuation is attached. Otherwise async or
>> executor-scheduled continuations would never launch. But maybe this is
>> meant and only deferred futures are mentioned here because for them waiting
>> on the inner result could be optional and also be deferred.
>>
> There have been quite a lot of changes respect to deferred futures.
> Please, could you see if there is still an issue?
>
I think this is still an issue. The paper describes that the inner future
is resolved upon the first wait() or get(). However we you use only
continuations these will never be called.
If I use the example from the paper without the last line:
auto f1 = async(launch::deferred, [] { return 1; });
auto f2 = f1.then([](future<int> n) { return 2; });
Then if f1.then uses the launch policy async either explicetly or
implicetly then the continuation would never run and complete f2.
In my opinion for async continuations (or executor continuations if they
come back) deferred futures would need to be resolved as soon as .then is
called or alternatively in the scheduler or other thread that starts the
continuation.
Only for .then calls which also use a deferred policy resolving of all the
results can be deferred until wait/get is called.
But on the other hand the requirement text only says that the inner future
get's resolved through wait/get - which is not wrong. It doesn't tell when
that happens.
The example does tell it - but it's probably wrong for an async
continuation.
> - make_ready_future can construct a ready future which is completed with a
>> given value. But it should also be possible to construct one which is
>> completed with an exception.
>>
> We have added make_exceptional_future.
>
Ok, I've seen that.
- future.unwrap():
>>
> unwrap has been removed.
>
- What happens when the future<future<T>> to unwrap has no associated
>> state? This could either throw an exception or return a default constructed
>> future<T> (which also has no state).
>>
> I think that this has been fixed. When the future is invalid an exception
> is set.
>
I think the point only applied in case of an explicit unwrap (that is now
removed). With the new revision there exists only the question what should
happen when you call .then on an invalid future.
I just searched for that again - but I don't think its explicetly
mentioned. Only the case what happens when the inner future get's invalid
later. Maybe I looked at the wrong place?
- Should the unwrapped future inherit the properties (launch policy,
>> executor) or the outer or inner future? As far as I can tell from my
>> implementation it can also inherit it from the outer future, because the
>> inner future is not guaranteed to exist at the point of the unwrapped
>> future's construction.
>>
> This point has not been discussed. Please could you open an issue at
> https://github.com/cplusplus/concurrency_ts/issues.
>
I can do that
> - Beeing able to check for an exception in a future an extracting it
>> without throwing would be helpful.
>>
> n4048 has proposed a exception_ptr_cast (get_exception_ptr) but this has
> not been retained yet.
>
Actually I meant something even simpler like bool future::has_error().
But of course get_exception_ptr in addition that that which allows to
retrieve the exception without throwing would be helpful too.
- I would like to have the ability to already set an executor (or maybe
>> also launch policy) as a constructor argument for the promise. This would
>> set the default executor for the associated promise. And if a continuation
>> gets attached with promise.get_future().then(func) it would be
>> automatically scheduled on this scheduler, without requiring the user to
>> explicetly specify the executor as a .then parameter.
>>
>
> While this could be convenient, it would make all the promise more
> expensive and needs a type erased executor.
>
> - I think the ability to retrieve the active executor of a running thread
>> would also be helpful, like std::executor*
>> std::this_executor::get_executor(). The active executor would have to be
>> stored in thread local storage. This function can for example be used to
>> easily run continuations on the same thread were the initial API call that
>> returned a future was made. E.g. when you call
>> file.read(1024bytes).then(...) inside the event loop of an UI framework the
>> read function could automatically set the default continuation executor to
>> the current thread's executor and the user can again avoid to explicetly
>> specify it. It would also help to check that some calls can only be made in
>> specific functions/executors.
>>
>
> In Boost.Thread I have added a hook to be run at the entry of a thread of
> an thread_pool. This entry can easily set a thread local variable usable by
> all the functions.
>
> template <class AtThreadEntry>
> basic_thread_pool( unsigned const thread_count, AtThreadEntry at_thread_entry);
>
>
> At thread entry
>
> It is common idiom to set some thread local variable at the beginning of a
> thread. As Executors could instantiate threads internally these Executors
> shall have the ability to call a user specific function at thread entry on
> the executor constructor.
>
> For executors that don't instantiate any thread and that would use the
> current thread this function shall be called only for the thread calling
> the at_thread_entry member function.
> Current executor
>
> The library does not provision for the ability to get the current
> executor, though having access to it could simplify a lot the user code.
>
> The reason is that the user can always use a thread_local variable and
> reset it using the at_thread_entry member function.
>
> thread_local current_executor_state_type current_executor_state;executor* current_executor() { return current_executor_state.current_executor(); }basic_thread_pool pool(
> // at_thread_entry
> [](basic_thread_pool& pool) {
> current_executor_state.set_current_executor(pool);
> });
>
> Default executor
>
> The library authors share some of the concerns of the C++ standard
> committee (introduction of a new single shared resource, a singleton, could
> make it difficult to make it portable to all the environments) and that
> this library doesn't need to provide a default executor for the time been.
>
> The user can always define his default executor himself and use the
> at_thread_entry member function to set the default constructor.
>
> thread_local default_executor_state_type default_executor_state;executor* default_executor() { return default_executor_state.default_executor(); }
> // in mainMyDefaultExecutor myDefaultExecutor(
> // at_thread_entry
> [](MyDefaultExecutor& ex) {
> default_executor_state.set_default_executor(ex);
> });
> basic_thread_pool pool(
> // at_thread_entry
> [&myDefaultExecutor](basic_thread_pool& pool) {
> default_executor_state.set_default_executor(myDefaultExecutor);
> });
>
> Ok, I understand that I can do it myself. I just thought that if an
executor interface gets standardized it might make sense to standardize the
way of storing the current executor too.
But if the new exeuctors specification now uses concepts instead of a type
erased interface it will make less sense anyway.
> E.g. in my IO library I currently have an executor which runs around an
>> epoll instance (could also be IOCP queue) - and only inside this executor
>> you are allowed to to IO calls. Besides that it could also be used for
>> deadlock detection: If the promise get's told through the constructor that
>> will be completed from inside a special executor then future<T>::get/wait()
>> could throw an exception when anyone tries to fetch the value from exactly
>> that executor.
>>
>
>
>> However getting the current executor might be a little bit tricky if
>> executors are nested, like with the proposed serial_executor. It would
>> either refer only to the most inner executor, or some kind of executor
>> stack / linked-list, or a executor::get_parent() function would be needed.
>>
>> Even if Executors can be nested, I don't see how a thread can run on two
> executors. Could you elaborate?
>
I thought about things like the windows eventloop (which is also kind of an
executor): When you have one window open the main thread runs the main
windowloop, but when you open a modal dialog then the windowloop of this
window is running (on the same thread) until it's closed again. Or about
Reactive Extensions - where your thread can drive any kind of scheduler
(e.g. the ComputationScheduler or NewThreadScheduler), but you can
additionally observe events on a CurrentThread or trampoline scheduler,
which will create a nested scheduler for some duration that executes
functions on the same thread.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_351_1437244875.1414352977447
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi, thanks for the answer,<br>my comments are below<br><br=
>Best regards<br>Matthias<br><div> </div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr">Hi everyone,<br><br>I started implementing parts of these pr=
oposals in order to build an async IO library on top of it.<br>I really lov=
e the idea and all the possibilites it provides.<br>However during the impl=
ementation a few questions and issues came up, that I would like to present=
here:<br><br>- The future member function is_ready() is also called only r=
eady() on page 12.<br></div></blockquote><div>I think this is fixed now. <b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">- Regardin=
g deferred futures the paper states: "If the parent has a policy of launch:=
:deferred and the continuation does not have a specified launch policy or s=
cheduler, then the parent is filled by immediately calling .wait() , and th=
e policy of the antecedent is launch::deferred". I think for deferred futur=
es the future has to be always waited upon in the moment when a continuatio=
n is attached. Otherwise async or executor-scheduled continuations would ne=
ver launch. But maybe this is meant and only deferred futures are mentioned=
here because for them waiting on the inner result could be optional and al=
so be deferred.<br></div></blockquote><div>There have been quite a lot of c=
hanges respect to deferred futures. Please, could you see if there is still=
an issue? <br></div></div></blockquote><div>I think this is still an issue=
.. The paper describes that the inner future is resolved upon the first wait=
() or get(). However we you use only continuations these will never be call=
ed.<br>If I use the example from the paper without the last line:<br><pre>a=
uto f1 =3D async(launch::deferred, [] { return 1; });
auto f2 =3D f1.then([](future<ins><int></ins> n) { return 2; });</pre=
>Then if f1.then uses the launch policy async either explicetly or implicet=
ly then the continuation would never run and complete f2.<br>In my opinion =
for async continuations (or executor continuations if they come back) defer=
red futures would need to be resolved as soon as .then is called or alterna=
tively in the scheduler or other thread that starts the continuation.<br>On=
ly for .then calls which also use a deferred policy resolving of all the re=
sults can be deferred until wait/get is called.<br>But on the other hand th=
e requirement text only says that the inner future get's resolved through w=
ait/get - which is not wrong. It doesn't tell when that happens.<br>The exa=
mple does tell it - but it's probably wrong for an async continuation.<br>&=
nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><d=
iv></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">- make_re=
ady_future can construct a ready future which is completed with a given val=
ue. But it should also be possible to construct one which is completed with=
an exception.<br></div></blockquote><div>We have added make_exceptional_fu=
ture. <br></div></div></blockquote><div>Ok, I've seen that.<br> <br><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">- future.unw=
rap(): <br></div></blockquote><div>unwrap has been removed.</div></div></bl=
ockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div=
></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"> &nbs=
p; - What happens when the future<future<T>> to unwrap has no a=
ssociated state? This could either throw an exception or return a default c=
onstructed future<T> (which also has no state).<br></div></blockquote=
><div>I think that this has been fixed. When the future is invalid an excep=
tion is set.<br></div></div></blockquote><div>I think the point only applie=
d in case of an explicit unwrap (that is now removed). With the new revisio=
n there exists only the question what should happen when you call .then on =
an invalid future.<br>I just searched for that again - but I don't think it=
s explicetly mentioned. Only the case what happens when the inner future ge=
t's invalid later. Maybe I looked at the wrong place?<br><br><br></div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><block=
quote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"> - Should t=
he unwrapped future inherit the properties (launch policy, executor) or the=
outer or inner future? As far as I can tell from my implementation it can =
also inherit it from the outer future, because the inner future is not guar=
anteed to exist at the point of the unwrapped future's construction.<br></d=
iv></blockquote><div>This point has not been discussed. Please could you op=
en an issue at <a href=3D"https://github.com/cplusplus/concurrency_ts/issue=
s" target=3D"_blank" onmousedown=3D"this.href=3D'https://www.google.com/url=
?q\75https%3A%2F%2Fgithub.com%2Fcplusplus%2Fconcurrency_ts%2Fissues\46sa\75=
D\46sntz\0751\46usg\75AFQjCNEXMgFnWxytX0m3bEXq3RB-slSsYQ';return true;" onc=
lick=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fgithub.co=
m%2Fcplusplus%2Fconcurrency_ts%2Fissues\46sa\75D\46sntz\0751\46usg\75AFQjCN=
EXMgFnWxytX0m3bEXq3RB-slSsYQ';return true;">https://github.com/cplusplus/<w=
br>concurrency_ts/issues</a>. <br></div></div></blockquote><div>I can do th=
at<br><br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
">- Beeing able to check for an exception in a future an extracting it with=
out throwing would be helpful.<br></div></blockquote><div>n4048 has propose=
d a exception_ptr_cast (get_exception_ptr) but this has not been retained y=
et. <br></div></div></blockquote><div>Actually I meant something even=
simpler like bool future::has_error().<br>But of course get_exception_ptr =
in addition that that which allows to retrieve the exception without throwi=
ng would be helpful too.<br> <br><br></div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr">- I would like to have the ability to already set an exec=
utor (or maybe also launch policy) as a constructor argument for the promis=
e. This would set the default executor for the associated promise. And if a=
continuation gets attached with promise.get_future().then(<wbr>func) it wo=
uld be automatically scheduled on this scheduler, without requiring the use=
r to explicetly specify the executor as a .then parameter.<br></div></block=
quote><div><br>While this could be convenient, it would make all the promis=
e more expensive and needs a type erased executor.<br><br></div><blockquote=
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px =
#ccc solid;padding-left:1ex"><div dir=3D"ltr">- I think the ability to retr=
ieve the active executor of a running thread would also be helpful, like st=
d::executor* std::this_executor::get_<wbr>executor(). The active executor w=
ould have to be stored in thread local storage. This function can for examp=
le be used to easily run continuations on the same thread were the initial =
API call that returned a future was made. E.g. when you call file.read(1024=
bytes).then(...) inside the event loop of an UI framework the read function=
could automatically set the default continuation executor to the current t=
hread's executor and the user can again avoid to explicetly specify it. It =
would also help to check that some calls can only be made in specific funct=
ions/executors. </div></blockquote><div><br>In Boost.Thread I have added a =
hook to be run at the entry of a thread of an thread_pool. This entry=
can easily set a thread local variable usable by all the functions.<br><br=
><pre> <span>template</span> <span><</span><span>class</span> <span>A=
tThreadEntry</span><span>></span>
<span>basic_thread_pool</span><span>(</span> <span>unsigned</span> <spa=
n>const</span> <span>thread_count</span><span>,</span> <span>AtThreadEntry<=
/span> <span>at_thread_entry</span><span>);</span></pre><br><h6><a>At
thread entry</a>
</h6>
<p>
It is common idiom to set some thread local variable at the begin=
ning of
a thread. As Executors could instantiate threads internally these=
Executors
shall have the ability to call a user specific function at thread=
entry
on the executor constructor.
</p>
<p>
For executors that don't instantiate any thread and that would us=
e the
current thread this function shall be called only for the thread =
calling
the <code><span>at_thread_entry</span></code> member
function.
</p>
<h6>
<a name=3D"c302cb07-ee9c-4712-8bd5-e91c6b534191@isocpp.org_thread.synchroni=
zation.executors.rationale.h3"></a>
<span><a name=3D"c302cb07-ee9c-4712-8bd5-e91c6b534191@isocpp.org_=
thread.synchronization.executors.rationale.cancelation"></a></span><a>Curre=
nt
executor</a>
</h6>
<p>
The library does not provision for the ability to get the current=
executor,
though having access to it could simplify a lot the user code.
</p>
<p>
The reason is that the user can always use a thread_local variabl=
e and
reset it using the <code><span>at_thread_entry</span>
</code> member function.
</p>
<pre><span>thread_local</span> <span>current_executor_state_type</span> <sp=
an>current_executor_state</span><span>;</span>
<span>executor</span><span>*</span> <span>current_executor</span><span>()</=
span> <span>{</span> <span>return</span> <span>current_executor_state</span=
><span>.</span><span>current<wbr>_executor</span><span>();</span> <span>}</=
span>
<span>basic_thread_pool</span> <span>pool</span><span>(</span>
<span>// at_thread_entry</span>
<span>[](</span><span>basic_thread_pool</span><span>&</span> <span>poo=
l</span><span>)</span> <span>{</span>
<span>current_executor_state</span><span>.</span><span>set_<wbr>current_e=
xecutor</span><span>(</span><span>pool</span><span>);</span>
<span>}</span>
<span>);</span>
</pre>
<h6>
<a name=3D"c302cb07-ee9c-4712-8bd5-e91c6b534191@isocpp.org_thread.synchroni=
zation.executors.rationale.h5"></a> <span></span><a>Default
executor</a>
</h6>
<p>
The library authors share some of the concerns of the C++ standar=
d committee
(introduction of a new single shared resource, a singleton, could=
make
it difficult to make it portable to all the environments) and tha=
t this
library doesn't need to provide a default executor for the time b=
een.
</p>
<p>
The user can always define his default executor himself and use t=
he <code><span>at_thread_entry</span> </code> member function to set
the default constructor.
</p>
<pre><span>thread_local</span> <span>default_executor_state_type</span> <sp=
an>default_executor_state</span><span>;</span>
<span>executor</span><span>*</span> <span>default_executor</span><span>()</=
span> <span>{</span> <span>return</span> <span>default_executor_state</span=
><span>.</span><span>default<wbr>_executor</span><span>();</span> <span>}</=
span>
<span>// in main</span>
<span>MyDefaultExecutor</span> <span>myDefaultExecutor</span><span>(</span>
<span>// at_thread_entry</span>
<span>[](</span><span>MyDefaultExecutor</span><span>&</span> <span>ex<=
/span><span>)</span> <span>{</span>
<span>default_executor_state</span><span>.</span><span>set_<wbr>default_e=
xecutor</span><span>(</span><span>ex</span><span>);</span>
<span>}</span>
<span>);</span>
<span>basic_thread_pool</span> <span>pool</span><span>(</span>
<span>// at_thread_entry</span>
<span>[&</span><span>myDefaultExecutor</span><span>](</span><span>basi=
c_<wbr>thread_pool</span><span>&</span> <span>pool</span><span>)</span>=
<span>{</span>
<span>default_executor_state</span><span>.</span><span>set_<wbr>default_e=
xecutor</span><span>(</span><span>myDefaultExec<wbr>utor</span><span>);</sp=
an>
<span>}</span>
<span>);</span></pre></div></div></blockquote><div>Ok, I understand that I =
can do it myself. I just thought that if an executor interface gets standar=
dized it might make sense to standardize the way of storing the current exe=
cutor too.<br>But if the new exeuctors specification now uses concepts inst=
ead of a type erased interface it will make less sense anyway. <br><br>&nbs=
p;<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">E.g. in my IO libra=
ry I currently have an executor which runs around an epoll instance (could =
also be IOCP queue) - and only inside this executor you are allowed t=
o to IO calls. Besides that it could also be used for deadlock detection: I=
f the promise get's told through the constructor that will be completed fro=
m inside a special executor then future<T>::get/wait() could throw an=
exception when anyone tries to fetch the value from exactly that executor.=
</div></blockquote><div> </div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">However getting the current executor might be a little b=
it tricky if executors are nested, like with the proposed serial_executor. =
It would either refer only to the most inner executor, or some kind of exec=
utor stack / linked-list, or a executor::get_parent() function would be nee=
ded.<br><br></div></blockquote><div>Even if Executors can be nested, I don'=
t see how a thread can run on two executors. Could you elaborate?<br></div>=
</div></blockquote><div>I thought about things like the windows eventloop (=
which is also kind of an executor): When you have one window open the main =
thread runs the main windowloop, but when you open a modal dialog then the =
windowloop of this window is running (on the same thread) until it's closed=
again. Or about Reactive Extensions - where your thread can drive any kind=
of scheduler (e.g. the ComputationScheduler or NewThreadScheduler), but yo=
u can additionally observe events on a CurrentThread or trampoline schedule=
r, which will create a nested scheduler for some duration that executes fun=
ctions on the same thread.<br></div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_351_1437244875.1414352977447--
.