Einen Thread erneut verwenden!

paddy_de

Grünschnabel
Ich hab ein Problem und zwar sitze ich gerade daran einen HTTP Server in "C" zu programmieren und da stellt sich natürlich früher oder später die aufgabe des Multithreadings mit Hilfe eines Threadpools. Genau an diesem Punkt bin ich nun auch angekommen und es stellt sich folgendes Problem:

Die 10 Threads erstelle ich am Anfang als CREATE_SUSPEND und beim ersten aufruf für jeden der zehn Threads aktiviere ich diesen mit ResumeThread und schläfer ihn am Ende wieder mit SuspendThread ein. Das Problem ist nun jedoch, wenn jeder der zehn Threads einmal etwas zu tun hatte und somit schonmal durch ResumeThread aktiviert und durch SuspendThread wieder schlafen gelegt wurde, bleibt mein Server hengen und reagiert nicht mehr! Ich kann also einen Thread nicht mehrmals verwenden.

Meine idee ist, dass ich einen Threadpool habe, den ich mit hilfe einer struktur aufbaue(linked list) und halt immer den ersten Thread benutze und ihn dann aus der linked list herausnehme! Wenn keine Threads mehr vorhanden sind, weil alle gerade verwendet werden, wird 30 sec gewartet.

ich hoffe es kann mir jemand weiterhelfen, bin schon ziemlich am verzweifeln!

Falls Quellcode benötigt wird, kann ich den später auch nochmal posten, brauche nur eine angabe, was genau benötigt wird! Weil alles wird ein bissl lang :D

Danke schonmal!
 

3Cyb3r

Erfahrenes Mitglied
Hmm ich verstehe den Sinn nicht ganz wieso du das ganze so machst. -.- evtl Quellcode posten
Irgendwie ist dein Programm auch nicht dynamisch sondern beschtänkt und das möchtest du änder sehe ich das richtig?
Mein Vorschlag:
Lege eine Liste mit Threads an (oder Pointer auf.. je nach belieben) und erstelle immer einen Thread wenn du ihn bracusht füg ihn in die Liste ein und wenn er seine aufgabe erfüllt hat einfach weider löschen.
 

paddy_de

Grünschnabel
Nein genau das möchte ich nicht, da das zu aufwendig ist und zu viel Geschwindigkeit kostet. Ein HTTP-Server wird in der Regel ja nur einmal irgendwann gestartet, es sei denn er ist down und man resetet ihn oder ähnliches und von daher ist es nicht so schlimm, wenn ich zu anfang alle Threads erstelle und somit eine längere Start zeit habe, als wenn ich bei jedem aufruf einen neuen Thread starte und diesen wieder lösche, wen er nicht mehr benötigit wird.


struct vom Threadpool:
Code:
typedef struct THREADPOOL_s
{
	LPDWORD wThreadID;
	CRITICAL_SECTION csectionAccept;
	HANDLE hThread;

	SOCKET sdAccept;
	fd_set rfds;
	bool bStopRunning;

	MYSQL *pMySQL; //!

	THREADPOOL_s *pThreadNext;
}
THREADPOOL_t;

init ThreadPool:
Code:
pStart_T = (THREADPOOL_t*) malloc(sizeof(THREADPOOL_t));

	if (pStart_T == NULL)
		return -1;

	memset(pStart_T, 0, sizeof(THREADPOOL_t));

	pStart_T->hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnThreadMessage, pStart_T, CREATE_SUSPENDED, pStart_T->wThreadID);
		
	if (pStart_T->hThread == NULL)
	{
		printf("errorcode: %d\n", GetLastError());
		cleanup(pStart_M, NULL);
		free(pStart_T);
		printf("Cannot create Thread!\n");
		return -1;
	}

	pTmp_T = pStart_T;
	
	for (i = 0; i < 10; i++)
	{
		
		pNew_T = (THREADPOOL_t *)malloc(sizeof(THREADPOOL_t));

		if (pNew_T == NULL)
		{
			cleanup(pStart_M, pStart_T);
			return -1;
		}

		memset(pNew_T, 0, sizeof(THREADPOOL_t));

		pNew_T->hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnThreadMessage, pNew_T, CREATE_SUSPENDED, pNew_T->wThreadID);
		
		if (pNew_T->hThread == NULL)
		{
			cleanup(pNew_M, pNew_T);
			printf("Cannot create Thread!\n");
			return -1;
		}

		pTmp_T->pThreadNext = pNew_T;
		pTmp_T = pNew_T;
	}

benutzen des Threads:
Code:
do
	{
		if (listen(sdListen, MAX_SERVER_CONNECTIONS) == -1)
		{
			printf("Error listen()\r\n");
			continue;
		}

		pThread = allocThreads();

		if (pThread->hThread == NULL)
		{
			//deleteMessage(pThread);
			free(pThread);
			printf("No Threads are available!\n");
		}
		else
		{
			pThread->sdAccept = accept(sdListen, NULL, NULL);

			if (pThread->sdAccept == -1)
			{
				releaseThread(pThread);
				printf("connection failed! socket\r\n");
				continue;
			}

			dwRet = ResumeThread(pThread->hThread);
			
			if (dwRet == -1)
			{
				printf("errorcode: %d\n", GetLastError());
				//deleteMessage(pThread);
				free(pThread);
				printf("Cannot resume Thread!\n");
				releaseThread(pThread);
			}
		}
}
	while (1);

alloc thread funktion:
Code:
static THREADPOOL_t* allocThreads()
{
	THREADPOOL_t *pActive, *pTMP;

	mutexlock(true);
	pTMP = pFirst_T;

	if (pTMP != NULL)
	{
		pActive = pTMP;
		pFirst_T = pTMP->pThreadNext;

		mutexlock(false);

		return pActive;
	}
	else
	{
		mutexlock(false);
		return NULL;
	}
}

thread hat seine aufgabe erledigt:
Code:
if (recvCommand(pThread) == 0)
	{
		iMySQLControl = 0;

		if (shutdown(pThread->sdAccept, 0) != 0)
			printf("shutdown-error(M)!\r\n");

		closesocket(pThread->sdAccept);
		killmutex(pThread);
		//deleteMessage(pThread);
		//free(pThread);
		printf("Connection: closed\r\n\r\n\r\n");
		releaseThread(pThread);

		return (void *) -1;
	}

zu guter letzt die release Thread Funktion:
Code:
void releaseThread(THREADPOOL_t *pThread)
{
	THREADPOOL_t *pTMP;
	DWORD dwRet;

	mutexlock(true);

	if (pFirst_T != NULL)
	{
		pTMP = pFirst_T;

		while (pTMP->pThreadNext != NULL)
			pTMP = pTMP->pThreadNext;

		pTMP->pThreadNext = pThread;
		pTMP->pThreadNext->pThreadNext = NULL;
	}
	else
	{
		pFirst_T = pThread;
		pFirst_T->pThreadNext = NULL;
	}

	mutexlock(false);
	dwRet = SuspendThread(pThread->hThread);

	if (dwRet == -1)
	{
		printf("errorcode: %d\n", GetLastError());
		exit(0);
	}
}




Ist jetzt warscheinlich alles recht unübersichtlich, da der Sourecode schon ziemlich komplex ist, falls jemand ne idee hat und den ganzen sourecode braucht bitte ne pm schreiben, dann kann ich es per email senden!

Danke!
 

Neue Beiträge