⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 list.c

📁 侯捷先生翻译的书籍《Win32多线程程序设计》的源代码。
💻 C
字号:
/*
 * 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, 0, 0, &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, 0, 0, &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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -