惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
H
Heimdal Security Blog
K
Kaspersky official blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
S
Schneier on Security
G
GRAHAM CLULEY
U
Unit 42
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
C
CERT Recently Published Vulnerability Notes
Google DeepMind News
Google DeepMind News
罗磊的独立博客
Stack Overflow Blog
Stack Overflow Blog
阮一峰的网络日志
阮一峰的网络日志
Simon Willison's Weblog
Simon Willison's Weblog
C
Cisco Blogs
Cyberwarzone
Cyberwarzone
T
The Exploit Database - CXSecurity.com
Project Zero
Project Zero
Security Archives - TechRepublic
Security Archives - TechRepublic
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园 - 司徒正美
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
V
Visual Studio Blog
博客园 - Franky
Engineering at Meta
Engineering at Meta
WordPress大学
WordPress大学
Jina AI
Jina AI
P
Proofpoint News Feed
P
Proofpoint News Feed
有赞技术团队
有赞技术团队
L
LINUX DO - 最新话题
宝玉的分享
宝玉的分享
N
News and Events Feed by Topic
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 聂微东
T
The Blog of Author Tim Ferriss
Spread Privacy
Spread Privacy
Application and Cybersecurity Blog
Application and Cybersecurity Blog
IT之家
IT之家
S
Security Affairs
博客园 - 叶小钗
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
小众软件
小众软件
N
News | PayPal Newsroom
Cloudbric
Cloudbric
AWS News Blog
AWS News Blog
W
WeLiveSecurity
The Last Watchdog
The Last Watchdog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
NISL@THU
NISL@THU

博客园 - 南守拥

DB2 sequence 迁移 申请认证 java monitor file java mina unix client asp.net 跑 socket server epoll 多线程 服务器 PAZU 是4Fang 为配合“四方在线”软件于2004年开发的WEB打印控件,适用于各种WEB软件项目的打印。 jbpm表说明 6-3 6-2 6-1 同步机制摘要 3-3 - 南守拥 - 博客园 3-2 - 南守拥 - 博客园 3-1 2-6 - 南守拥 - 博客园 2-4 - 南守拥 - 博客园 2-3 - 南守拥 - 博客园 2-2 - 南守拥 - 博客园
7-1
南守拥 · 2010-07-12 · via 博客园 - 南守拥

ReadWrit.h

/*
 * ReadWrit.h
 *
 * Sample code for Multithreading Applications in Win32
 * This is from Chapter 7, Listing 7-1
 *
 * Demonstrates an implementation of the
 * Readers/Writers algorithm. This version
 * gives preference to readers.
 
*////////////////////////////////////////////////////////

//
// Structure definition
//

typedef 
struct _RWLock
{
    
// Handle to a mutex that allows
    
// a single reader at a time access
    
// to the reader counter.
    HANDLE    hMutex;// Handle to a semaphore that keeps
    
// the data locked for either the
    
// readers or the writers.
    HANDLE    hDataLock;// The count of the number of readers.
    
// Can legally be zero or one while
    
// a writer has the data locked.
    int        nReaderCount;
} RWLock;
//
// Reader/Writer prototypes
//

BOOL InitRWLock(RWLock 
*pLock);
BOOL DestroyRWLock(RWLock 
*pLock);
BOOL AcquireReadLock(RWLock 
*pLock);
int ReleaseReadLock(RWLock *pLock);
BOOL AcquireWriteLock(RWLock 
*pLock);
int ReleaseWriteLock(RWLock *pLock);
BOOL ReadOK(RWLock 
*pLock);
BOOL WriteOK(RWLock 
*pLock);

BOOL FatalError(

char *s);

代码

/*
 * ReadWrit.c
 *
 * Sample code for "Multithreading Applications in Win32"
 * This is from Chapter 7, various listings.
 *
 * Demonstrates an implementation of the
 * Readers/Writers algorithm. This version
 * gives preference to readers.
 
*/#define WIN32_LEAN_AND_MEAN
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<windows.h>
#include 
"ReadWrit.h"// If we wait more than 2 seconds, then something is probably wrong!
#define MAXIMUM_TIMEOUT 2000// Here's the pseudocode for what is going on:
//
// Lock for Reader:
//  Lock the mutex
//  Bump the count of readers
//  If this is the first reader, lock the data
//  Release the mutex
//
// Unlock for Reader:
//  Lock the mutex
//  Decrement the count of readers
//  If this is the last reader, unlock the data
//  Release the mutex
//
// Lock for Writer:
//  Lock the data
//
// Unlock for Reader:
//  Unlock the data

///////////////////////////////////////////////////////

BOOL MyWaitForSingleObject(HANDLE hObject)
{
    DWORD result;

    result 

= WaitForSingleObject(hObject, MAXIMUM_TIMEOUT);
    
// Comment this out if you want this to be non-fatal
    if (result != WAIT_OBJECT_0)
        FatalError(
"MyWaitForSingleObject - Wait failed, you probably forgot to call release!");
    
return (result == WAIT_OBJECT_0);
}

BOOL InitRWLock(RWLock 

*pLock)
{
    pLock
->nReaderCount = 0;
    pLock
->hDataLock = CreateSemaphore(NULL, 11, NULL);
    
if (pLock->hDataLock == NULL)
        
return FALSE;
    pLock
->hMutex = CreateMutex(NULL, FALSE, NULL);
    
if (pLock->hMutex == NULL)
    {
        CloseHandle(pLock
->hDataLock);
        
return FALSE;
    }
    
return TRUE;
}

BOOL DestroyRWLock(RWLock 

*pLock)
{
    DWORD result 
= WaitForSingleObject(pLock->hDataLock, 0);
    
if (result == WAIT_TIMEOUT)
        
return FatalError("DestroyRWLock - Can't destroy object, it's locked!");

    CloseHandle(pLock

->hMutex);
    CloseHandle(pLock
->hDataLock);
    
return TRUE;
}

BOOL AcquireReadLock(RWLock 

*pLock)
{
    BOOL result 
= TRUE;if (!MyWaitForSingleObject(pLock->hMutex))
        
return FALSE;
 
    
if(++pLock->nReaderCount == 1)
        result 
= MyWaitForSingleObject(pLock->hDataLock);

    ReleaseMutex(pLock

->hMutex);
    
return result;
}

BOOL ReleaseReadLock(RWLock 

*pLock)
{
    
int result;
    LONG lPrevCount;
if (!MyWaitForSingleObject(pLock->hMutex))
        
return FALSE;if (--pLock->nReaderCount == 0)
        result 
= ReleaseSemaphore(pLock->hDataLock, 1&lPrevCount);

    ReleaseMutex(pLock

->hMutex);
    
return result;
}

BOOL AcquireWriteLock(RWLock 

*pLock)
{
    
return MyWaitForSingleObject(pLock->hDataLock);
}

BOOL ReleaseWriteLock(RWLock 

*pLock)
{
    
int result;
    LONG lPrevCount;

    result 

= ReleaseSemaphore(pLock->hDataLock, 1&lPrevCount);
    
if (lPrevCount != 0)
        FatalError(
"ReleaseWriteLock - Semaphore was not locked!");
    
return result;
}

BOOL ReadOK(RWLock 

*pLock)
{
    
// This check is not perfect, because we
    
// do not know for sure if we are one of
    
// the readers.
    return (pLock->nReaderCount > 0);
}

BOOL WriteOK(RWLock 

*pLock)
{
    DWORD result;
// The first reader may be waiting in the mutex,
    
// but any more than that is an error.
    if (pLock->nReaderCount > 1)
        
return FALSE;// This check is not perfect, because we
    
// do not know for sure if this thread was
    
// the one that had the semaphore locked.
    result = WaitForSingleObject(pLock->hDataLock, 0);
    
if (result == WAIT_TIMEOUT)
        
return TRUE;// a count is kept, which was incremented in Wait.
    result = ReleaseSemaphore(pLock->hDataLock, 1, NULL);
    
if (result == FALSE)
        FatalError(
"WriteOK - ReleaseSemaphore failed");
    
return FALSE;
}
///////////////////////////////////////////////////////

/*
 * Error handler
 
*/
BOOL FatalError(
char *s)
{
    fprintf(stdout, 
"%s\n", s);
    
// Comment out exit() to prevent termination
    exit(EXIT_FAILURE);
    
return FALSE;
}

代码

/*
 * List.c
 *
 * Sample code for "Multithreading Applications in Win32"
 * This is from Chapter 7, Listing 7-1
 *
 * Demonstrates an implementation of the
 * Readers/Writers algorithm. This version
 * gives preference to readers.
 
*/#define WIN32_LEAN_AND_MEAN
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<windows.h>
#include 
"ReadWrit.h"///////////////////////////////////////////////////////

//
// Structure definition
//

typedef 
struct _Node
{
    
struct _Node *pNext;
    
char    szBuffer[80];
} Node;

typedef 

struct _List
{
    RWLock    
lock;
    Node    
*pHead;
} List;
//
// Linked list prototypes
//

BOOL InitRWLock(RWLock 
*pLock);
BOOL DeleteList(List 
*pList);
BOOL AddHead(List 
*pList, Node *node);
BOOL DeleteHead(List 
*pList);
BOOL Insert(List 
*pList, Node *afterNode, Node *newNode);
Node 
*Next(List *pList, Node *node);//
// Test functions prototypes
//

DWORD WINAPI LoadThreadFunc(LPVOID n);
DWORD WINAPI SearchThreadFunc(LPVOID n);
DWORD WINAPI DeleteThreadFunc(LPVOID n);
//
// Global variables
//// This is the list we use for testing
List *gpList;///////////////////////////////////////////////////////

List 
*CreateList()
{
    List 
*pList = GlobalAlloc(GPTR, sizeof(List));
    
if (InitRWLock(&pList->lock== FALSE)
    {
        GlobalFree(pList);
        pList 
= NULL;
    }
    
return pList;
}

BOOL DeleteList(List 

*pList)
{
    AcquireWriteLock(
&pList->lock);
    
while (DeleteHead(pList))
        ;
    ReleaseWriteLock(
&pList->lock);

    DestroyRWLock(

&gpList->lock);

    GlobalFree(pList);

return TRUE;
}

BOOL AddHead(List 

*pList, Node *pNode)
{
    
if (!WriteOK(&pList->lock))
        
return FatalError("AddHead - not allowed to write!");

    pNode

->pNext = pList->pHead;
    pList
->pHead = pNode;
}

BOOL DeleteHead(List 

*pList)
{
    Node 
*pNode;if (!WriteOK(&pList->lock))
        
return FatalError("AddHead - not allowed to write!");if (pList->pHead == NULL)
        
return FALSE;

    pNode 

= pList->pHead->pNext;
    GlobalFree(pList
->pHead);
    pList
->pHead = pNode;
    
return TRUE;
}

BOOL Insert(List 

*pList, Node *afterNode, Node *newNode)
{
    
if (!WriteOK(&pList->lock))
        
return FatalError("Insert - not allowed to write!");if (afterNode == NULL)
    {
        AddHead(pList, newNode);
    }
    
else
    {
        newNode
->pNext = afterNode->pNext;
        afterNode
->pNext = newNode;
    }
}

Node 

*Next(List *pList, Node *pNode)
{
    
if (!ReadOK(&pList->lock))
    {
        FatalError(
"Next - Not allowed to read!");
        
return NULL;
    }
if (pNode == NULL)
        
return pList->pHead;
    
else
        
return pNode->pNext;
}
///////////////////////////////////////////////////////

DWORD WINAPI ThreadFunc(LPVOID);
int main()
{
    HANDLE  hThrds[
4];
    
int     slot = 0;
    
int        rc;
    
int        nThreadCount = 0;
    DWORD    dwThreadId;

    gpList 

= CreateList();
    
if (!gpList)
        FatalError(
"main - List creation failed!");

    hThrds[nThreadCount

++= CreateThread(NULL,
        
0, LoadThreadFunc, 00&dwThreadId );

    hThrds[nThreadCount

++= CreateThread(NULL,
        
0, SearchThreadFunc, (LPVOID)"pNode"0&dwThreadId );

    hThrds[nThreadCount

++= CreateThread(NULL,
        
0, SearchThreadFunc, (LPVOID)"pList"0&dwThreadId );

    hThrds[nThreadCount

++= CreateThread(NULL,
        
0, DeleteThreadFunc, 00&dwThreadId );/* Now wait for all threads to terminate */
    rc 
= WaitForMultipleObjects(
        nThreadCount,
        hThrds,
        TRUE,
        INFINITE );
for (slot=0; slot<nThreadCount; slot++)
        CloseHandle(hThrds[slot]);
    printf(
"\nProgram finished.\n");

    DeleteList(gpList);

return EXIT_SUCCESS;
}
/*
 * Slowly load the contents of "List.c" into the
 * linked list.
 
*/
DWORD WINAPI LoadThreadFunc(LPVOID n)
{
    
int nBatchCount;
    Node 
*pNode;

    FILE

* fp = fopen("List.c""r");
    
if (!fp)
    {
        fprintf(stderr, 
"ReadWrit.c not found\n");
        exit(EXIT_FAILURE);
    }

    pNode 

= GlobalAlloc(GPTR, sizeof(Node));
    nBatchCount 
= (rand() % 10+ 2;
    AcquireWriteLock(
&gpList->lock);while (fgets(pNode->szBuffer, sizeof(Node), fp))
    {
        AddHead(gpList, pNode);
// Try not to hog the lock
        if (--nBatchCount == 0)
        {
            ReleaseWriteLock(
&gpList->lock);
            Sleep(rand() 
% 5);
            nBatchCount 
= (rand() % 10+ 2;
            AcquireWriteLock(
&gpList->lock);
        }
        pNode 
= GlobalAlloc(GPTR, sizeof(Node));
    }

    ReleaseWriteLock(

&gpList->lock);
    
return 0;
}
/*
 * Every so often, walked the linked list
 * and figure out how many lines one string
 * appears (given as the startup param)
 
*/
DWORD WINAPI SearchThreadFunc(LPVOID n)
{
    
int i;
    
char *szSearch = (char *)n;for (i=0; i<20; i++)
    {
        
int        nFoundCount = 0;
        Node   
*next = NULL;

        AcquireReadLock(

&gpList->lock);
        next 
= Next(gpList, next);
        
while (next)
        {
            
if (strstr(next->szBuffer, szSearch))
                nFoundCount
++;
            next 
= Next(gpList, next);
        }

        ReleaseReadLock(

&gpList->lock);

        printf(

"Found %d lines with '%s'\n", nFoundCount, szSearch);
        Sleep((rand() 
% 30));
    }
    
return 0;
}
/*
 * Every so often, delete some entries in the list.
 
*/
DWORD WINAPI DeleteThreadFunc(LPVOID n)
{
    
int i;for (i=0; i<100; i++)
    {
        Sleep(
1);
        AcquireWriteLock(
&gpList->lock);
        DeleteHead(gpList);
        DeleteHead(gpList);
        DeleteHead(gpList);
        ReleaseWriteLock(
&gpList->lock);
    }
return 0;
}

od