std.parallelism changes done

Sönke Ludwig ludwig at informatik.uni-luebeck.de
Thu Mar 24 18:05:58 PDT 2011


Am 24.03.2011 14:25, schrieb dsimcha:
> On 3/24/2011 3:00 AM, Sönke Ludwig wrote:
>> Am 24.03.2011 05:32, schrieb dsimcha:
>>> In addition to improving the documentation, I added
>>> Task.executeInNewThread() to allow Task to be useful without a TaskPool.
>>> (Should this have a less verbose name?)
>>
>> The threading system I designed for the company I work for uses priority
>> per task to control which tasks can overtake others. A special priority
>> is out-of-bands (the name my be debatable), which will guarantee that
>> the task will run in its own thread so it can safely wait for other
>> tasks.
>
> This may not be an issue in the std.parallelism design. A TaskPool task
> can safely wait on other tasks. What prevents this from causing a
> deadlock is that calling yieldForce, spinForce, or waitForce on a task
> that has not started executing yet will execute the task immediately in
> the thread that tried to force it, regardless of where it is in the queue.

Indeed this pattern solves the problem to wait for the completion of a 
specific task. It also avoids a huge potential of deadlocks that a 
general yield() that does not take a task would have. However, it will 
not solve the general problem of one task waiting for another, which 
could be in terms of a condition variable or just a mutex that is used 
in the middle of the task execution.

>
> However, those threads that process OOB tasks are also cached in
>> the thread pool and reused for new OOB tasks. Only if the number of
>> parallel OOB tasks goes over a specific number, new threads will be
>> created and destroyed. This can safe quite a bit of time for those tasks.
>
> Unfortunately this is not implementable without a massive overhaul of
> TaskPool. There are some baked in assumptions that the number of worker
> threads in a pool will not change after the pool's creation.
> Furthermore, I'm not sure how worker-local storage would be efficiently
> implementable without this restriction.
>
>>
>> Both kinds of priority have been very useful and I would suggest to put
>> at least the executeInNewThread() method into ThreadPool to be later
>> able to make such an optimization.
>
> Can you elaborate on this? The whole point of executeInNewThread() was
> supposed to be that a TaskPool is not needed for simple cases.

Well OK if that is the only purpose to provide a shortcut for (new 
Thread(&fun)).start then my suggestion may not make too much sense. 
However, I have some doubts that the advantage to have this shortcut 
here justifies the functional duplication of core.thread. Is there some 
specific use case where you would use a Task object but not a ThreadPool?

But what I wanted to say is, even if it may be difficult to implement 
such thread caching now, putting means to execute a Task in its own 
thread now into the ThreadPool allows for such an optimization later (it 
could even exist while still keeping Task.executeInNewThread()).

Btw. another more advanced thing that is interesting is to use IO 
completion ports to dynamically increase the number of threads in cases 
of contention or IO waits. But this is of course a whole different story 
and I certainly would not expect this to get in at this stage or maybe 
ever. Just wanted to throw that in.


More information about the Digitalmars-d mailing list