Re: [boost] [gsoc-2013] Boost.Thread/ThreadPool project

Le 29/04/13 21:35, Niall Douglas a ?crit : Could you explain me what a central asynchronous dispatcher is? An asynchronous procedure call implementation. Here's Microsoft's: http://msdn.microsoft.com/en- us/library/windows/desktop/ms681951(v=vs.85).as px. Here's QNX's: http://www.qnx.com/developers/articles/article_870_1.html. Boost.ASIO is the same thing for Boost and C++ but implemented by application code. It is *not* like asynchronous POSIX signals which are a nearly useless subset of APCs. I don't see the term "central asynchronous dispatcher" used in any of
Le 30/04/13 17:16, Niall Douglas a ?crit : the links. Could you clarify what it is?
If not, please could you elaborate what kind of optimizations can be obtained? If you have transactional memory in particular, you gain multi-CAS and
I have to admit I'm struggling to see where your block is, but Dave Abrahams often found the same with me, so it must be me. A central asynchronous dispatcher is the loop which sends callbacks/events to be invoked/processed by other execution contexts. Every OS has at least one in the kernel. Most GUI toolkits like Qt have one. Boost has at least one in the form of Boost.ASIO. The central means one execution context does the dispatch. The asynchronous means that callbacks are processed by recipients asynchronous to the dispatcher. And dispatcher, well that dispatches. the
ability to (un)lock large ranges of CAS locks atomically, and a central dispatcher design can create batch lists of threading primitive operations and execute the batch at once as a transaction. Without TM, you really need the kernel to provide a batch syscall for threading primitives to see large performance gains. I'm really lost.
Multi-word Compare-And-Swap (MCAS) is one of the biggest gains from Transactional Memory. Indeed WG21 has SG5 dedicated to integrating TM into C++17. Some models of Intel's Haswell come with hardware TM assist. I'd take a reasonable guess that MCAS will benefit centralized kernel-based threading primitives architectures such as Windows NT more than decentralized threading primitive architectures such as POSIX. That said, I could see Linux using TM for batch multi-kernel-futex ops, though I'd have to say implementing that without breakage would be daunting. Either way, a central asynchronous dispatcher has information a decentralized implementation does not. That opens more scope for optimization.
Boost.ASIO's core is boost::asio::io_service. That is its dispatcher implementation which each dispatch execution context being executed via boost::asio::io_service::run() which is effectively an event loop. Third parties then enqueue items to be dispatched using boost::asio::io_service::post(). You don't have to run Boost.ASIO using multiple threads: it can be single threaded.
I could not comment until I understand what Boost.ASIO provides and it can interact with thread_pools :(
Boost.ASIO provides a per-thread capable event loop implementation. That automatically makes it an example of a thread pool manager. You may find N3562 Executors and schedulers coproposed March 2013 for Bristol by Google and Microsoft of use to you in understanding the relation between thread pools and Boost.ASIO (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3562.pdf). My proposed Boost.AFIO library is an implementation of that same N3562 idea, albeit I extend Boost.ASIO which is IMHO more C++-y whereas Google and Microsoft have gone with proprietary implementations. Also, they include timing and many other more general purpose features, and mine does not (currently) as it's mainly aimed at maximising input/ouput with highly jittery random latency storage. Niall --- Opinions expressed here are my own and do not necessarily represent those of BlackBerry Inc.

Le 29/04/13 21:35, Niall Douglas a ?crit : Could you explain me what a central asynchronous dispatcher is? An asynchronous procedure call implementation. Here's Microsoft's: http://msdn.microsoft.com/en- us/library/windows/desktop/ms681951(v=vs.85).as px. Here's QNX's: http://www.qnx.com/developers/articles/article_870_1.html. Boost.ASIO is the same thing for Boost and C++ but implemented by application code. It is *not* like asynchronous POSIX signals which are a nearly useless subset of APCs. I don't see the term "central asynchronous dispatcher" used in any of
Le 30/04/13 17:16, Niall Douglas a ?crit : the links. Could you clarify what it is? I have to admit I'm struggling to see where your block is, but Dave Abrahams often found the same with me, so it must be me. It is just that I don't know the term. As I don't know the domain (the words) you are talking about we can stop
Le 01/05/13 20:39, Niall Douglas a écrit : the exchange here if you prefer, or you could continue to explaining me the things I don't know/understand.
A central asynchronous dispatcher is the loop which sends callbacks/events to be invoked/processed by other execution contexts. Every OS has at least one in the kernel. Most GUI toolkits like Qt have one. Boost has at least one in the form of Boost.ASIO.
The central means one execution context does the dispatch. The asynchronous means that callbacks are processed by recipients asynchronous to the dispatcher. And dispatcher, well that dispatches.
In order to be sure I understand what you say could you tell me how a decentralized asynchronous dispatcher behaves? What are the differences?
If not, please could you elaborate what kind of optimizations can be obtained? If you have transactional memory in particular, you gain multi-CAS and the ability to (un)lock large ranges of CAS locks atomically, and a central dispatcher design can create batch lists of threading primitive operations and execute the batch at once as a transaction. Without TM, you really need the kernel to provide a batch syscall for threading primitives to see large performance gains. I'm really lost. Multi-word Compare-And-Swap (MCAS) is one of the biggest gains from Transactional Memory. Indeed WG21 has SG5 dedicated to integrating TM into C++17. Some models of Intel's Haswell come with hardware TM assist.
I'd take a reasonable guess that MCAS will benefit centralized kernel-based threading primitives architectures such as Windows NT more than decentralized threading primitive architectures such as POSIX. That said, I could see Linux using TM for batch multi-kernel-futex ops, though I'd have to say implementing that without breakage would be daunting.
Either way, a central asynchronous dispatcher has information a decentralized implementation does not. That opens more scope for optimization.
Are you saying that current TM technology should be much more useful for centralized than decentralized asynchronous dispatchers? Does this means that the whole application would improve its performances using always centralized asynchronous dispatchers?
Boost.ASIO's core is boost::asio::io_service. That is its dispatcher implementation which each dispatch execution context being executed via boost::asio::io_service::run() which is effectively an event loop. Third parties then enqueue items to be dispatched using boost::asio::io_service::post(). You don't have to run Boost.ASIO using multiple threads: it can be single threaded. I could not comment until I understand what Boost.ASIO provides and it can interact with thread_pools :( Boost.ASIO provides a per-thread capable event loop implementation. That automatically makes it an example of a thread pool manager.
You may find N3562 Executors and schedulers coproposed March 2013 for Bristol by Google and Microsoft of use to you in understanding the relation between thread pools and Boost.ASIO (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3562.pdf).
I know this proposal. Could you explain me how it is related to Boost.Asio? Could you point me where in the Asio documentation could I find related information?
My proposed Boost.AFIO library is an implementation of that same N3562 idea, albeit I extend Boost.ASIO which is IMHO more C++-y whereas Google and Microsoft have gone with proprietary implementations. Also, they include timing and many other more general purpose features, and mine does not (currently) as it's mainly aimed at maximising input/ouput with highly jittery random latency storage.
Thanks Niall for all the explanations and sorry if all this is trivial for you. Vicente

Le 01/05/13 23:08, Vicente J. Botet Escriba a écrit :
Le 01/05/13 20:39, Niall Douglas a écrit :
It is just that I don't know the term. As I don't know the domain (the words) you are talking about we can stop the exchange here if you prefer, or you could continue to explaining me the things I don't know/understand.
I have just read N3388 - Using Asio with C++11 and a think I start to understand the ASIO design. Could we say the completion handlers are continuations? And that the user use to master which thread executes the continuation by calling the io_service::run() function? And that io_service can have associated also several threads (to form a thread pool). And that in order to avoid data races the user uses strands to serialize the completion handlers that have access to shared data? While continuation passing style could be well adapted to protocols (and surely it is) , there are other domains that would prefer to write his code in a more linear way. It is true that with C++11 lambdas the continuation passing style is less opaque. I hope that now I would be able to understand your concerns better. Vicente

Hello, I have updated my proposal following your guide and tried to answer and give solution to most of the problems. I have tried to separate the interface with the implementation details so when choosing an interface a feature can be easily added by following the exact interface header so multiple implementations can be used without affecting the user(ex: scheduling algorithm for dynamic thereads, bounded/unbounded queues etc). I hope this approach is better. You can find the pdf version here [1]. The previous version of the proposal can be found here [2]. Thank you very much for the feedback, suggestions, guidance and the really fast answers. [1] http://danlincan.3owl.com/gsoc/final-proposal.pdf [2] http://danlincan.3owl.com/gsoc/Proposal.pdf Regards, Dan

Le 02/05/13 11:58, Dan Lincan a écrit :
Hello,
I have updated my proposal following your guide and tried to answer and give solution to most of the problems. I have tried to separate the interface with the implementation details so when choosing an interface a feature can be easily added by following the exact interface header so multiple implementations can be used without affecting the user(ex: scheduling algorithm for dynamic thereads, bounded/unbounded queues etc). I hope this approach is better.
You can find the pdf version here [1]. The previous version of the proposal can be found here [2].
Thank you very much for the feedback, suggestions, guidance and the really fast answers.
[1] http://danlincan.3owl.com/gsoc/final-proposal.pdf [2] http://danlincan.3owl.com/gsoc/Proposal.pdf
Hi Dan, *The new proposal contains:* *Waitable tasks* This feature gives the user the option to wait for a task to finish and retrieve its result. Drawback is that maybe the user is not interested in the result of the task. Interface template<classFunction,class...Args > boost::future<typenameboost::result_of<Functionf()>::type> submit(Function&&f, Args&&args); My comments: what do you think of separating the responsabilities, the thread pool schedules Callables (void()) and a submit free function manage with futures: class thread_pool { public: template<class Callable > void submit(Callable&&); ... }; template<typename, Executor, class Function,class... Args > boost::future<typename boost::result_of<Function (Args...)>::type> submit(Executor& e, Function&& f, Args&& args); Implementing this function needs to use the same techniques than boost::async()* The new proposal contains:* *Task scheduling priority* The user would be allowed to give the tasks a priority, something similar to the operating system process priority: low, medium, high etc. Performance is lost when the algorithm to schedule tasks is running. Based on the implementation, this can be more that O(1), thus big overhead. Another problem is fair scheduling. Low priority tasks have to run at some point even if only high priority tasks are being submitted to the threadpool. Interface template<classFunction,class...Args ,class Priority> boost::future<typenameboost::result_of<Functionf()>::type> submit(Function&&f, Args&&args, Priorityp = default_priority()); My comments: I don't think adding priorities in this way would improve the performances. *The new proposal contains:* *Task execution order* For example the user might want x tasks to be executed, then only after all x have been executed another y can be executed and so on. So the user could assign the priority 1 to the x tasks and 2 to y tasks. The threadpool will know that level 2 tasks can only be executed after level 1 tasks are done. Performance is lost when a task is chosen to be executed. For example, if using priority queues, the complexity would be O(logn) plus the locks which can slow down a lot the scheduling. This feature can be used as a kind of serial executor by giving higher and higher numbers to the order argument. Interface template<class Function,class...Args ,class Order> boost::future<typenameboost::result_of<Functionf()>::type> *submit**(**Function**&&***f*, **Args&&*args*, **Order*o= default_order()); *Callback functions / Continuations* The user can also set a callback function when submitting a task to the threadpool. This function will run as soon as the task is finished by the threadpool. Drawback: Since the callback function is runned by the thread which executs the task, this thread can be block if the callback function is blocking. Also the callback has no parameters. Interface template<class Function,class...Args ,class Callback> boost::future<typenameboost::result_of<Functionf()>::type> *submit**(**Function**&&***f*, **Args&&*args*, **Callback*c= default_callback()); My comments: I prefer continuations than callbacks and prefer an interface that explicitly states the dependencies. when_all(submit(f), submit(g)).then(h); *The new proposal contains:* *Task cancellation* With this feature the use can cancel a submitted task. If the task is currently being executed it will be interrupted. For implementation boost::thread::intterupts will be activated. template<class Function,class...Args ,class Callback,class Task> boost::future<typenameboost::result_of<Functionf()>::type> *submit**(**Function**&&***f*, **Args&&*args*, ****Task&*task); Task has the function cancel which cancels/interrupts when called. My comments: This is a little bit complex from the users point of view. I guess the best is to either: * adding to boost::future the possibility to interrupt the task, or * returning a interrupted_future<T> or task<T> that can be interrupted. There is an additional requirement. The user must ensure that all the tasks related to some object are executed sequentially but the task submission don't knows about the pending tasks. Continuations don't solve the problem. What would you add to make the users life easier? (please read the discussion about threadpool and ASIO, the answer is someway there). Best, Vicente

Hi Vincente, I'm sorry but I can't give you proper answers now because l don't have internet access on my computer at my current location. I will get back home in 2 days. Regards, Dan On May 2, 2013 6:16 PM, "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr> wrote:
Le 02/05/13 11:58, Dan Lincan a écrit :
Hello,
I have updated my proposal following your guide and tried to answer and give solution to most of the problems. I have tried to separate the interface with the implementation details so when choosing an interface a feature can be easily added by following the exact interface header so multiple implementations can be used without affecting the user(ex: scheduling algorithm for dynamic thereads, bounded/unbounded queues etc). I hope this approach is better.
You can find the pdf version here [1]. The previous version of the proposal can be found here [2].
Thank you very much for the feedback, suggestions, guidance and the really fast answers.
[1] http://danlincan.3owl.com/**gsoc/final-proposal.pdf<http://danlincan.3owl.com/gsoc/final-proposal.pdf> [2] http://danlincan.3owl.com/**gsoc/Proposal.pdf<http://danlincan.3owl.com/gsoc/Proposal.pdf>
Hi Dan,
*The new proposal contains:*
*Waitable tasks*
This feature gives the user the option to wait for a task to finish and retrieve its result.
Drawback is that maybe the user is not interested in the result of the task.
Interface
template<classFunction,class..**.Args >
boost::future<typenameboost::**result_of<Functionf()>::type>
submit(Function&&f, Args&&args);
My comments:
what do you think of separating the responsabilities, the thread pool schedules Callables (void()) and a submit free function manage with futures:
class thread_pool { public:
template<class Callable > void submit(Callable&&); ... };
template<typename, Executor, class Function,class... Args > boost::future<typename boost::result_of<Function (Args...)>::type> submit(Executor& e, Function&& f, Args&& args);
Implementing this function needs to use the same techniques than boost::async()*
The new proposal contains:*
*Task scheduling priority*
The user would be allowed to give the tasks a priority, something similar to the operating system process priority: low, medium, high etc.
Performance is lost when the algorithm to schedule tasks is running. Based on the implementation, this can be more that O(1), thus big overhead. Another problem is fair scheduling. Low priority tasks have to run at some point even if only high priority tasks are being submitted to the threadpool.
Interface
template<classFunction,class..**.Args ,class Priority>
boost::future<typenameboost::**result_of<Functionf()>::type>
submit(Function&&f, Args&&args, Priorityp = default_priority());
My comments:
I don't think adding priorities in this way would improve the performances.
*The new proposal contains:*
*Task execution order*
For example the user might want x tasks to be executed, then only after all x have been executed another y can be executed and so on. So the user could assign the priority 1 to the x tasks and 2 to y tasks. The threadpool will know that level 2 tasks can only be executed after level 1 tasks are done.
Performance is lost when a task is chosen to be executed. For example, if using priority queues, the complexity would be O(logn) plus the locks which can slow down a lot the scheduling.
This feature can be used as a kind of serial executor by giving higher and higher numbers to the order argument.
Interface
template<class Function,class...Args ,class Order>
boost::future<typenameboost::**result_of<Functionf()>::type>
*submit**(**Function**&&***f*, **Args&&*args*, **Order*o= default_order());
*Callback functions / Continuations*
The user can also set a callback function when submitting a task to the threadpool. This function will run as soon as the task is finished by the threadpool.
Drawback: Since the callback function is runned by the thread which executs the task, this thread can be block if the callback function is blocking. Also the callback has no parameters.
Interface
template<class Function,class...Args ,class Callback>
boost::future<typenameboost::**result_of<Functionf()>::type>
*submit**(**Function**&&***f*, **Args&&*args*, **Callback*c= default_callback());
My comments:
I prefer continuations than callbacks and prefer an interface that explicitly states the dependencies.
when_all(submit(f), submit(g)).then(h);
*The new proposal contains:*
*Task cancellation*
With this feature the use can cancel a submitted task. If the task is currently being executed it will be interrupted. For implementation boost::thread::intterupts will be activated.
template<class Function,class...Args ,class Callback,class Task>
boost::future<typenameboost::**result_of<Functionf()>::type>
*submit**(**Function**&&***f*, **Args&&*args*, ****Task&*task);
Task has the function cancel which cancels/interrupts when called.
My comments:
This is a little bit complex from the users point of view. I guess the best is to either: * adding to boost::future the possibility to interrupt the task, or * returning a interrupted_future<T> or task<T> that can be interrupted.
There is an additional requirement. The user must ensure that all the tasks related to some object are executed sequentially but the task submission don't knows about the pending tasks. Continuations don't solve the problem. What would you add to make the users life easier? (please read the discussion about threadpool and ASIO, the answer is someway there).
Best, Vicente
______________________________**_________________ Unsubscribe & other changes: http://lists.boost.org/** mailman/listinfo.cgi/boost<http://lists.boost.org/mailman/listinfo.cgi/boost>

*The new proposal contains:*
*Waitable tasks*
This feature gives the user the option to wait for a task to finish and retrieve its result.
Drawback is that maybe the user is not interested in the result of the task.
Interface
template<classFunction,class...Args >
boost::future<typenameboost::result_of<Functionf()>::type>
submit(Function&&f, Args&&args);
My comments:
what do you think of separating the responsabilities, the thread pool schedules Callables (void()) and a submit free function manage with futures:
class thread_pool { public:
template<class Callable > void submit(Callable&&); ... };
template<typename, Executor, class Function,class... Args > boost::future<typename boost::result_of<Function (Args...)>::type> submit(Executor& e, Function&& f, Args&& args);
Implementing this function needs to use the same techniques than boost::async()*
What techniques from boost::async() are you referring to?
The new proposal contains:*
*Task scheduling priority*
The user would be allowed to give the tasks a priority, something similar to the operating system process priority: low, medium, high etc.
Performance is lost when the algorithm to schedule tasks is running. Based on the implementation, this can be more that O(1), thus big overhead. Another problem is fair scheduling. Low priority tasks have to run at some point even if only high priority tasks are being submitted to the threadpool.
Interface
template<classFunction,class...Args ,class Priority>
boost::future<typenameboost::result_of<Functionf()>::type>
submit(Function&&f, Args&&args, Priorityp = default_priority());
My comments:
I don't think adding priorities in this way would improve the performances.
Well I thought about adding priorities this way to achieve close to O(1) performance. I had in mind something similar to counting sort. As long as we know that we have at most x priorities level ( in this case x=3: low, medium, high ), we can store the tasks in an array of containers(queue/lock-free queue/others) so submitting a task to the threadpool can be done in O(1). The only problem after this is having to deal with fair scheduling. This can be done in O(1) too so O(1) performance overall.
*The new proposal contains:*
*Task execution order*
For example the user might want x tasks to be executed, then only after all x have been executed another y can be executed and so on. So the user could assign the priority 1 to the x tasks and 2 to y tasks. The threadpool will know that level 2 tasks can only be executed after level 1 tasks are done.
Performance is lost when a task is chosen to be executed. For example, if using priority queues, the complexity would be O(logn) plus the locks which can slow down a lot the scheduling.
This feature can be used as a kind of serial executor by giving higher and higher numbers to the order argument.
Interface
template<class Function,class...Args ,class Order>
boost::future<typenameboost::result_of<Functionf()>::type>
*submit**(**Function**&&***f*, **Args&&*args*, **Order*o= default_order());
*Callback functions / Continuations*
The user can also set a callback function when submitting a task to the threadpool. This function will run as soon as the task is finished by the threadpool.
Drawback: Since the callback function is runned by the thread which executs the task, this thread can be block if the callback function is blocking. Also the callback has no parameters.
Interface
template<class Function,class...Args ,class Callback>
boost::future<typenameboost::result_of<Functionf()>::type>
*submit**(**Function**&&***f*, **Args&&*args*, **Callback*c= default_callback());
My comments:
I prefer continuations than callbacks and prefer an interface that explicitly states the dependencies.
when_all(submit(f), submit(g)).then(h);
This is what I had in mind with this feature. I should have been more clear as this is the reason I have added [1] as reference.
*The new proposal contains:*
*Task cancellation*
With this feature the use can cancel a submitted task. If the task is currently being executed it will be interrupted. For implementation boost::thread::intterupts will be activated.
template<class Function,class...Args ,class Callback,class Task>
boost::future<typenameboost::result_of<Functionf()>::type>
*submit**(**Function**&&***f*, **Args&&*args*, ****Task&*task);
Task has the function cancel which cancels/interrupts when called.
My comments:
This is a little bit complex from the users point of view. I guess the best is to either: * adding to boost::future the possibility to interrupt the task, or * returning a interrupted_future<T> or task<T> that can be interrupted.
Then I would prefer the first alternative, extending boost::future. For the user it would be really nice to use just result.interrupt() where result is a future.
There is an additional requirement. The user must ensure that all the tasks related to some object are executed sequentially but the task submission don't knows about the pending tasks. Continuations don't solve the problem. What would you add to make the users life easier? (please read the discussion about threadpool and ASIO, the answer is someway there).
I will search it and get back with an answer. [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3558.pdf Regards, Dan

Le 07/05/13 12:57, Dan Lincan a écrit :
*The new proposal contains:*
*Waitable tasks*
This feature gives the user the option to wait for a task to finish and retrieve its result.
Drawback is that maybe the user is not interested in the result of the task.
Interface
template<classFunction,class...Args >
boost::future<typenameboost::result_of<Functionf()>::type>
submit(Function&&f, Args&&args);
My comments:
what do you think of separating the responsabilities, the thread pool schedules Callables (void()) and a submit free function manage with futures:
class thread_pool { public:
template<class Callable > void submit(Callable&&); ... };
template<typename, Executor, class Function,class... Args > boost::future<typename boost::result_of<Function (Args...)>::type> submit(Executor& e, Function&& f, Args&& args);
Implementing this function needs to use the same techniques than boost::async()* What techniques from boost::async() are you referring to? boost::async is able to build waiting futures that synchronize with the end of the task.
The new proposal contains:*
*Task scheduling priority*
The user would be allowed to give the tasks a priority, something similar to the operating system process priority: low, medium, high etc.
Performance is lost when the algorithm to schedule tasks is running. Based on the implementation, this can be more that O(1), thus big overhead. Another problem is fair scheduling. Low priority tasks have to run at some point even if only high priority tasks are being submitted to the threadpool.
Interface
template<classFunction,class...Args ,class Priority>
boost::future<typenameboost::result_of<Functionf()>::type>
submit(Function&&f, Args&&args, Priorityp = default_priority());
My comments:
I don't think adding priorities in this way would improve the performances. Well I thought about adding priorities this way to achieve close to O(1) performance. I had in mind something similar to counting sort. As long as we know that we have at most x priorities level ( in this case x=3: low, medium, high ), we can store the tasks in an array of containers(queue/lock-free queue/others) so submitting a task to the threadpool can be done in O(1). The only problem after this is having to deal with fair scheduling. This can be done in O(1) too so O(1) performance overall. Ok. I see.
*The new proposal contains:*
*Task execution order*
For example the user might want x tasks to be executed, then only after all x have been executed another y can be executed and so on. So the user could assign the priority 1 to the x tasks and 2 to y tasks. The threadpool will know that level 2 tasks can only be executed after level 1 tasks are done.
Performance is lost when a task is chosen to be executed. For example, if using priority queues, the complexity would be O(logn) plus the locks which can slow down a lot the scheduling.
This feature can be used as a kind of serial executor by giving higher and higher numbers to the order argument.
Interface
template<class Function,class...Args ,class Order>
boost::future<typenameboost::result_of<Functionf()>::type>
*submit**(**Function**&&***f*, **Args&&*args*, **Order*o= default_order());
*Callback functions / Continuations*
The user can also set a callback function when submitting a task to the threadpool. This function will run as soon as the task is finished by the threadpool.
Drawback: Since the callback function is runned by the thread which executs the task, this thread can be block if the callback function is blocking. Also the callback has no parameters.
Interface
template<class Function,class...Args ,class Callback>
boost::future<typenameboost::result_of<Functionf()>::type>
*submit**(**Function**&&***f*, **Args&&*args*, **Callback*c= default_callback());
My comments:
I prefer continuations than callbacks and prefer an interface that explicitly states the dependencies.
when_all(submit(f), submit(g)).then(h); This is what I had in mind with this feature. I should have been more clear as this is the reason I have added [1] as reference. Great.
*The new proposal contains:*
*Task cancellation*
With this feature the use can cancel a submitted task. If the task is currently being executed it will be interrupted. For implementation boost::thread::intterupts will be activated.
template<class Function,class...Args ,class Callback,class Task>
boost::future<typenameboost::result_of<Functionf()>::type>
*submit**(**Function**&&***f*, **Args&&*args*, ****Task&*task);
Task has the function cancel which cancels/interrupts when called.
My comments:
This is a little bit complex from the users point of view. I guess the best is to either: * adding to boost::future the possibility to interrupt the task, or * returning a interrupted_future<T> or task<T> that can be interrupted. Then I would prefer the first alternative, extending boost::future. For the user it would be really nice to use just result.interrupt() where result is a future. Great.
There is an additional requirement. The user must ensure that all the tasks related to some object are executed sequentially but the task submission don't knows about the pending tasks. Continuations don't solve the problem. What would you add to make the users life easier? (please read the discussion about threadpool and ASIO, the answer is someway there). I will search it and get back with an answer.
[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3558.pdf & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Best, Vicente

Dan wrote on Thursday, May 2, 2013 at 13:58:35:
Hello,
I have updated my proposal following your guide and tried to answer and give solution to most of the problems. I have tried to separate the interface with the implementation details so when choosing an interface a feature can be easily added by following the exact interface header so multiple implementations can be used without affecting the user(ex: scheduling algorithm for dynamic thereads, bounded/unbounded queues etc). I hope this approach is better.
You can find the pdf version here [1]. The previous version of the proposal can be found here [2].
Thank you very much for the feedback, suggestions, guidance and the really fast answers.
[1] http://danlincan.3owl.com/gsoc/final-proposal.pdf [2] http://danlincan.3owl.com/gsoc/Proposal.pdf
perhaps not _this_ time, that is not this 2013 GSOC, but eventually you may want to consider a lock-free priority queue algorithm for storing tasks and not use locks although lock-free algorithms are somewhat hard to comprehend, all the more so about _priority_ queues, but in the end that's, beside other things, what one would expect from modern implementation of thread pool moreover, you, as a student loving algorithms and analysis, may like to dig into the lock-free algorithms in general good luck -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

Thank you very much for the feedback, suggestions, guidance and the really fast answers. [1] http://danlincan.3owl.com/gsoc/final-proposal.pdf [2] http://danlincan.3owl.com/gsoc/Proposal.pdf
Dan wrote on Thursday, May 2, 2013 at 13:58:35: perhaps not _this_ time, that is not this 2013 GSOC, but eventually you may want to consider a lock-free priority queue algorithm for storing tasks and not use locks It was in my mind to reuse Boos.LookFree queue. Why do you need a
Le 02/05/13 17:24, pavel a écrit : priority queue here?
although lock-free algorithms are somewhat hard to comprehend, all the more so about _priority_ queues, but in the end that's, beside other things, what one would expect from modern implementation of thread pool
moreover, you, as a student loving algorithms and analysis, may like to dig into the lock-free algorithms in general
Vicente

Vicente wrote on Thursday, May 2, 2013 at 22:40:06:
Thank you very much for the feedback, suggestions, guidance and the really fast answers. [1] http://danlincan.3owl.com/gsoc/final-proposal.pdf [2] http://danlincan.3owl.com/gsoc/Proposal.pdf
Dan wrote on Thursday, May 2, 2013 at 13:58:35: perhaps not _this_ time, that is not this 2013 GSOC, but eventually you may want to consider a lock-free priority queue algorithm for storing tasks and not use locks It was in my mind to reuse Boos.LookFree queue. Why do you need a
Le 02/05/13 17:24, pavel a écrit : priority queue here?
dan write in his proposal (the first link above) about task scheduling priority and that the implementation may require a priority queue with locks i just pointed out that it will be interesting to use particularly lock-free priority queue for that purpose instead of locking algorithm certainly, if boost.lockfree already had priority queue, one must have been (re)used that implementation, and in fact it's a pity that boost.lockfree hasn't one (as well as some kind of map/set) as for priority task scheduling -- i consider it an essential feature of a threadpool facility that certainly should be there and yes, boost absolutely needs a threadpool implementation i hope this project will be a good start -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

perhaps not _this_ time, that is not this 2013 GSOC, but eventually you may want to consider a lock-free priority queue algorithm for storing tasks and not use locks
although lock-free algorithms are somewhat hard to comprehend, all the more so about _priority_ queues, but in the end that's, beside other things, what one would expect from modern implementation of thread pool
moreover, you, as a student loving algorithms and analysis, may like to dig into the lock-free algorithms in general
good luck
Hi Pavel, I have read a bit about lock-free data structures in Concurrency in Action by Anthony Williams. Depending on the frozen interfaces and the time on hand I will most likely implement and do some performance tests for lock-free queues. Thank you, Dan

Le 02/05/13 11:58, Dan Lincan a écrit :
Hello,
I have updated my proposal following your guide and tried to answer and give solution to most of the problems. I have tried to separate the interface with the implementation details so when choosing an interface a feature can be easily added by following the exact interface header so multiple implementations can be used without affecting the user(ex: scheduling algorithm for dynamic thereads, bounded/unbounded queues etc). I hope this approach is better.
You can find the pdf version here [1]. The previous version of the proposal can be found here [2].
Thank you very much for the feedback, suggestions, guidance and the really fast answers.
[1] http://danlincan.3owl.com/gsoc/final-proposal.pdf [2] http://danlincan.3owl.com/gsoc/Proposal.pdf
Dan, are you there? Vicente

Hi Vincente, On Wed, May 1, 2013 at 11:42 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote: [...]
I have just read N3388 - Using Asio with C++11 and a think I start to understand the ASIO design. Could we say the completion handlers are continuations? And that the user use to master which thread executes the continuation by calling the io_service::run() function?
Pretty much, except that multiple threads can call io_service::run concurrently. Basically Boost.Asio is a work sharing queue plus a collection of waitqueues to wait for specific events.
And that io_service can have associated also several threads (to form a thread pool).
The associated threads are exactly those that are currently calling io_service::run.
And that in order to avoid data races the user uses strands to serialize the completion handlers that have access to shared data?
That's one way, but not the only way.
While continuation passing style could be well adapted to protocols (and surely it is) , there are other domains that would prefer to write his code in a more linear way. It is true that with C++11 lambdas the continuation passing style is less opaque.
That's orthogonal. Boost.Asio provides the funding blocks. A nicer interface that doesn't require an explicit continuation passing style transformation can be built with Boost.Context or a similar library. But it probably needs a future implementation that integrates with ASIO, which is one of the point of Niall Douglas. See the recent discussion about "library support for async/await pattern". -- gpd
participants (5)
-
Dan Lincan
-
Giovanni Piero Deretta
-
Niall Douglas
-
pavel
-
Vicente J. Botet Escriba