<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx</link><description>And, for whatever reason, the NT&amp;rsquo;s built-in thread pool API doesn&amp;rsquo;t work for you. Most people would write something like the following (error checking removed to reduce typing (and increase clarity)): class WorkItem { LIST_ENTRY m_listEntry;</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#103300</link><pubDate>Tue, 30 Mar 2004 11:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:103300</guid><dc:creator>Shmuel Baron</dc:creator><description>Larry, what do you think about using the APC mechanism to implement this? Each thread has an APC queue, you could queue APCs to each thread in your pool in a round robbin fashion, or any other load balancing mechanism you wish, with the QueueUserAPC function. That should eliminate the lock convoys problem. Then have each thread use SleepEx to wait in an alertable wait state so it could execute the APCs when it gets some, and once it finished executing all the APCs go back to sleep. The OS manages the FIFO APC queue for you, so you don't have to worry about it either.&lt;br&gt;</description></item><item><title>re: So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#103816</link><pubDate>Tue, 30 Mar 2004 18:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:103816</guid><dc:creator>Larry Osterman</dc:creator><description>Grrgh.  I had written an answer to you but somehow it got lost.&lt;br&gt;&lt;br&gt;Lets try again.&lt;br&gt;&lt;br&gt;That's a fascinating idea that I hadn't even considered before.&lt;br&gt;&lt;br&gt;In my model, you have a pool of idempotent worker threads, which pick work up as needed and execute on it.&lt;br&gt;&lt;br&gt;In your model, you have effectively two pools of threads - those that are idle and those that are doing work.&lt;br&gt;&lt;br&gt;The only negative to your idea is that you need to know which thread is receiving the APC - you can't ever queue an APC to a thread that's actually doing work because (a) the thread might not wait interruptably for a long time, and (b) because the thread MIGHT wait interruptably and accidentally pick up your second APC and start executing it before it had finished its work - this could cause deadlocks or memory corruption.&lt;br&gt;&lt;br&gt;To track this, you need to know which threads are processing work requests and which threads are idle, and only queue the requests to the idle threads.&lt;br&gt;&lt;br&gt;It's more overhead than my solution, and the code to manage the thread state is also potentially subject to lock convoys, but...&lt;br&gt;&lt;br&gt;I'm not saying it's a bad idea, it's not, but there is some subtlty in the solution that might bite you on the foot in the future if you're not careful.&lt;br&gt;</description></item><item><title>re: So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#105439</link><pubDate>Thu, 01 Apr 2004 09:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:105439</guid><dc:creator>Mike Dimmick</dc:creator><description>You don't mention that the completion port API also tries to limit the number of threads running simultaneously; if there's work to be done, but more than a given number of worker threads (associated with this port) are already running, NT won't release another thread. IIRC, this limit is 2x number of (virtual?) CPUs in the system.&lt;br&gt;&lt;br&gt;Conversely, when a thread associated with a completion port blocks (e.g. to perform synchronous I/O), NT looks to see if it can release another thread to keep the CPU busy. If there are fewer than the above limit threads running, there are threads blocked on the completion port, and there's work queued, NT will release a thread to replace the one that blocked.&lt;br&gt;&lt;br&gt;The net effect is to prevent context thrashing - where the scheduler spends more time trying to divide CPU time fairly among all the threads than the threads actually manage to get work done.&lt;br&gt;&lt;br&gt;At least, that's my recollection from Richter (Programming Applications for Windows, 4th ed, or it might be in Programming Server-Side Applications).</description></item><item><title>re: So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#105618</link><pubDate>Thu, 01 Apr 2004 15:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:105618</guid><dc:creator>Larry Osterman</dc:creator><description>You're totally right Mike, I didn't include that (mostly for lack of time).&lt;br&gt;&lt;br&gt;See, there are LOTS of reasons to use completion ports for your work queues.&lt;br&gt;</description></item><item><title>Things you shouldn't do, part 2: Dll's can't ever call CoInitialize* on the application's thread.</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#130542</link><pubDate>Wed, 12 May 2004 19:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:130542</guid><dc:creator>Larry Osterman's WebLog</dc:creator><description /></item><item><title>re: So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#143293</link><pubDate>Thu, 27 May 2004 20:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:143293</guid><dc:creator>Scott</dc:creator><description>So...  is there a way to query the number of items currently waiting in the queue?</description></item><item><title>re: So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#143313</link><pubDate>Thu, 27 May 2004 20:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:143313</guid><dc:creator>Larry Osterman</dc:creator><description>Nope.  &lt;br&gt;&lt;br&gt;The thing to keep in mind is that the number of items in the queue is meaningless.  The microsecond after the value's loaded into the variable that holds the count, it's no longer valid.&lt;br&gt;&lt;br&gt;You can't make decisions based on the value because by the time you get the value it's not valid.  So the NT guys don't give you the ability to screw it up.&lt;br&gt;</description></item><item><title>re: So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#143554</link><pubDate>Fri, 28 May 2004 03:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:143554</guid><dc:creator>Scott</dc:creator><description>I'm actually trying to use the ATL:CThreadPool class (which uses I/O completion ports) to queue up a long list of tasks (~6000) that take quite some time to finish - the whole process takes around 24 hours.  I am looking for a way to tell when the queue has emptied in order to move to the next phase of my application.  Am I barking up the wrong tree?</description></item><item><title>re: So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#143587</link><pubDate>Fri, 28 May 2004 05:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:143587</guid><dc:creator>Larry Osterman</dc:creator><description>Hmm...  That's a good question...&lt;br&gt;&lt;br&gt;Are you doing this on an MP machine?  Are the tasks disk intensive?  Since the CPU can only do one thing at a time, I'm wondering if queuing to the ATL::CThreadPool is the best idea.&lt;br&gt;&lt;br&gt;But anyway, since I don't know what you're doing, I can't speak to that.&lt;br&gt;&lt;br&gt;In your case, I'd just keep a counter - when you queue an item, increment it (with InterlockedIncrement), when you've processed a work item, you decrement it (InterlockedDecrement).  When the count goes to 0, you're done.&lt;br&gt;&lt;br&gt;The general case can't work because NT can't know why you want the count of items, but in your specific case, since you know you won't be queuing new items, you can make it work.&lt;br&gt;&lt;br&gt;One gotcha - the count might go to 0 before you've finished queueing the items, especially on an MP machine, so you shouldn't check the count until you've queued all the tasks.&lt;br&gt;</description></item><item><title>re: So you need a worker thread pool...</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#150349</link><pubDate>Mon, 07 Jun 2004 20:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:150349</guid><dc:creator>jbn</dc:creator><description>Another way would be to post a specific item that marks the end of the adding of items to the queue. Just create this special item before going MT, then in each worker thread, test the item you just retrieved from the queue against the special item, and if they're equal, just exit.&lt;br&gt;</description></item><item><title>Why does Win32 even have Fibers?</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#347319</link><pubDate>Thu, 06 Jan 2005 02:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:347319</guid><dc:creator>Larry Osterman's WebLog</dc:creator><description /></item><item><title>Why does Win32 even have Fibers?</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#350094</link><pubDate>Mon, 10 Jan 2005 22:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:350094</guid><dc:creator>Larry Osterman's WebLog</dc:creator><description /></item><item><title>Concurrency, Part 9 - APIs that enable scalable programming</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#383687</link><pubDate>Wed, 02 Mar 2005 20:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:383687</guid><dc:creator>Larry Osterman's WebLog</dc:creator><description /></item><item><title>Concurrency, Part 9 - APIs that enable scalable programming</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#383695</link><pubDate>Wed, 02 Mar 2005 20:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:383695</guid><dc:creator>Larry Osterman's WebLog</dc:creator><description /></item><item><title>It's Getting Crowded in the ThreadPool</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#676252</link><pubDate>Mon, 24 Jul 2006 05:35:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:676252</guid><dc:creator>K. Scott Allen</dc:creator><description>It seems everybody loves the thread pool. The default scheduler in Windows Workflow uses the thread pool,...</description></item><item><title>A high waiter count on a free critical section may indicate a lock convoy</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#1266393</link><pubDate>Tue, 12 Dec 2006 18:00:07 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1266393</guid><dc:creator>The Old New Thing</dc:creator><description>&lt;p&gt;Nobody can make any progress because they keep getting stuck.&lt;/p&gt;
</description></item><item><title>Threading deep dive – Day 8</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#8831272</link><pubDate>Mon, 04 Aug 2008 18:31:36 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8831272</guid><dc:creator>My Adventures with Microsoft Technologies</dc:creator><description>&lt;p&gt;Volatile Read / Writes MSDN says &amp;quot; The volatile modifier is usually used for a field that is accessed&lt;/p&gt;
</description></item><item><title> Larry Osterman s WebLog So you need a worker thread pool | Insomnia Cure</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#9719585</link><pubDate>Wed, 10 Jun 2009 03:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9719585</guid><dc:creator> Larry Osterman s WebLog So you need a worker thread pool | Insomnia Cure</dc:creator><description>&lt;p&gt;PingBack from &lt;a rel="nofollow" target="_new" href="http://insomniacuresite.info/story.php?id=9259"&gt;http://insomniacuresite.info/story.php?id=9259&lt;/a&gt;&lt;/p&gt;
</description></item><item><title> Larry Osterman s WebLog So you need a worker thread pool | Cellulite Creams</title><link>http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx#9720791</link><pubDate>Wed, 10 Jun 2009 04:45:09 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9720791</guid><dc:creator> Larry Osterman s WebLog So you need a worker thread pool | Cellulite Creams</dc:creator><description>&lt;p&gt;PingBack from &lt;a rel="nofollow" target="_new" href="http://cellulitecreamsite.info/story.php?id=8889"&gt;http://cellulitecreamsite.info/story.php?id=8889&lt;/a&gt;&lt;/p&gt;
</description></item></channel></rss>