<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.technet.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>Designing Applications for High Performance - Part II</title><link>http://blogs.technet.com/winserverperformance/archive/2008/05/21/designing-applications-for-high-performance-part-ii.aspx</link><description>Rick Vicik - Architect, Windows Server Performance Team The second part of this series covers Data Structures and Locks. I will provide general guidance on which data structures to use under certain circumstances and how to use locks without having a</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: Designing Applications for High Performance - Part II</title><link>http://blogs.technet.com/winserverperformance/archive/2008/05/21/designing-applications-for-high-performance-part-ii.aspx#3127978</link><pubDate>Thu, 25 Sep 2008 01:19:37 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3127978</guid><dc:creator>Mike</dc:creator><description>&lt;P&gt;&amp;nbsp;// program to demonstrate producer/consumer using SLIST&lt;/P&gt;
&lt;P&gt;#define INCL_BASE&lt;BR&gt;#include &amp;lt;windows.h&amp;gt;&lt;BR&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;typedef struct _WORK_ITEM {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SLIST_ENTRY ItemEntry;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ULONG Data;&lt;BR&gt;} WORK_ITEM;&lt;/P&gt;
&lt;P&gt;SLIST_HEADER ListHead;&lt;BR&gt;HANDLE DataReady;&lt;/P&gt;
&lt;P&gt;void Consumer (DWORD n)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WORK_ITEM *pWorkItem, *pPrev, *Temp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(;;) {&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // grab entire list&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pWorkItem = (WORK_ITEM*)InterlockedFlushSList(&amp;amp;ListHead);&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( pWorkItem ) {&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // reverse to process FIFO (if required)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( pPrev=NULL; pWorkItem; pWorkItem=Temp ) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Temp = (WORK_ITEM*)pWorkItem-&amp;gt;ItemEntry.Next;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pWorkItem-&amp;gt;ItemEntry.Next = (SLIST_ENTRY*)pPrev;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pPrev = pWorkItem;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pWorkItem = pPrev;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // process each item in local list&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( ; pWorkItem; pWorkItem = (WORK_ITEM*)pWorkItem-&amp;gt;ItemEntry.Next ) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("Data=%d\n", pWorkItem-&amp;gt;Data);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // check list again before waiting&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // if list was empty, wait to be signaled&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaitForSingleObject(DataReady,INFINITE);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;main(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int&amp;nbsp;&amp;nbsp; argc,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char* argv[]&lt;BR&gt;){&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WORK_ITEM *pWorkItem;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int i;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; InitializeSListHead(&amp;amp;ListHead);&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DataReady = CreateEvent(NULL,FALSE,FALSE,NULL);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Consumer, (LPVOID)0, 0, NULL);&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // add 10 items&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( i=0; i&amp;lt;10; i++ ) {&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pWorkItem = (WORK_ITEM*)_aligned_malloc(sizeof(WORK_ITEM), MEMORY_ALLOCATION_ALIGNMENT);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pWorkItem-&amp;gt;Data = i;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // if adding this item drives list from empty to non-empty, wake consumer&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( !InterlockedPushEntrySList(&amp;amp;ListHead, &amp;amp;(pWorkItem-&amp;gt;ItemEntry)) ) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetEvent(DataReady);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // test program only, wait for consumer to process all items&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while( QueryDepthSList(&amp;amp;ListHead) ) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sleep(1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;Do you have sample code on how to create a producer/consumer queue with s-list?&lt;/P&gt;</description></item></channel></rss>