Running constant number of threads.
-
Hi all. I need to emplement some problem, that its part is constantly running, for example, 20 threads. I use the followong code:
#include <windows.h> #include <stdio.h> int counter = 0; int released = 0; int limit; int maxNumberOfThreads = 20; HANDLE threadCreator; HANDLE threadHandle; DWORD threadID; void Release() { CloseHandle(threadHandle); CloseHandle(threadCreator); } void Initilize() { limit = 0; threadCreator = CreateSemaphore(NULL, 0, 50, NULL); if(threadCreator) { Release(); } } DWORD WINAPI Start( LPVOID lpParam ) { WaitForSingleObject(threadCreator, INFINITE); printf("ID = %d\n", GetCurrentThreadId()); --limit; ++released; ReleaseSemaphore(threadCreator, 1, NULL); return TRUE; } void StartSimulation() { while(true) { if(limit < maxNumberOfThreads) { threadHandle = CreateThread(NULL, 0, Start, NULL, 0, &threadID); if(!threadHandle) { Release(); } ++limit; ++counter; } if (counter == 100) break; } WaitForSingleObject(threadHandle, INFINITE); printf("Created %d threads.\nRelease %d threads.\n", counter, released); } int main() { Initilize(); StartSimulation(); Release(); return 0; }
I understand that there is something wrong. Any ideas how to fix it and to make this work? Thanks in advance. -
Hi all. I need to emplement some problem, that its part is constantly running, for example, 20 threads. I use the followong code:
#include <windows.h> #include <stdio.h> int counter = 0; int released = 0; int limit; int maxNumberOfThreads = 20; HANDLE threadCreator; HANDLE threadHandle; DWORD threadID; void Release() { CloseHandle(threadHandle); CloseHandle(threadCreator); } void Initilize() { limit = 0; threadCreator = CreateSemaphore(NULL, 0, 50, NULL); if(threadCreator) { Release(); } } DWORD WINAPI Start( LPVOID lpParam ) { WaitForSingleObject(threadCreator, INFINITE); printf("ID = %d\n", GetCurrentThreadId()); --limit; ++released; ReleaseSemaphore(threadCreator, 1, NULL); return TRUE; } void StartSimulation() { while(true) { if(limit < maxNumberOfThreads) { threadHandle = CreateThread(NULL, 0, Start, NULL, 0, &threadID); if(!threadHandle) { Release(); } ++limit; ++counter; } if (counter == 100) break; } WaitForSingleObject(threadHandle, INFINITE); printf("Created %d threads.\nRelease %d threads.\n", counter, released); } int main() { Initilize(); StartSimulation(); Release(); return 0; }
I understand that there is something wrong. Any ideas how to fix it and to make this work? Thanks in advance.You limit the maximal number of thread as 20, but in the while loop you test
if(counter == 100) break;
. Thecounter
stops at value = 20. The loop can never break.
Maxwell Chen
-
You limit the maximal number of thread as 20, but in the while loop you test
if(counter == 100) break;
. Thecounter
stops at value = 20. The loop can never break.
Maxwell Chen
Maxwell Chen wrote:
You limit the maximal number of thread as 20, but in the while loop you test if(counter == 100) break;. The counter stops at value = 20. The loop can never break.
You are wrong. counter increased every time the thread created.
++counter;
There limit also decreased in the Start function:--limit;
-
Maxwell Chen wrote:
You limit the maximal number of thread as 20, but in the while loop you test if(counter == 100) break;. The counter stops at value = 20. The loop can never break.
You are wrong. counter increased every time the thread created.
++counter;
There limit also decreased in the Start function:--limit;
Evgeni57 wrote:
You are wrong. counter increased every time the thread created.
I just traced your code step-by-step, and saw that.
++counter
can only happen when the test (below) is true:if(limit < maxNumberOfThreads)
Maxwell Chen
-
Hi all. I need to emplement some problem, that its part is constantly running, for example, 20 threads. I use the followong code:
#include <windows.h> #include <stdio.h> int counter = 0; int released = 0; int limit; int maxNumberOfThreads = 20; HANDLE threadCreator; HANDLE threadHandle; DWORD threadID; void Release() { CloseHandle(threadHandle); CloseHandle(threadCreator); } void Initilize() { limit = 0; threadCreator = CreateSemaphore(NULL, 0, 50, NULL); if(threadCreator) { Release(); } } DWORD WINAPI Start( LPVOID lpParam ) { WaitForSingleObject(threadCreator, INFINITE); printf("ID = %d\n", GetCurrentThreadId()); --limit; ++released; ReleaseSemaphore(threadCreator, 1, NULL); return TRUE; } void StartSimulation() { while(true) { if(limit < maxNumberOfThreads) { threadHandle = CreateThread(NULL, 0, Start, NULL, 0, &threadID); if(!threadHandle) { Release(); } ++limit; ++counter; } if (counter == 100) break; } WaitForSingleObject(threadHandle, INFINITE); printf("Created %d threads.\nRelease %d threads.\n", counter, released); } int main() { Initilize(); StartSimulation(); Release(); return 0; }
I understand that there is something wrong. Any ideas how to fix it and to make this work? Thanks in advance.The problems in the code are various. There are problems with basic thread and semaphore managment. I have to guess at what the code is trying to do: create up to 20 simultaneous threads and wait until until a maximum of 100 threads have been created. Each thread uses a semaphore to block thread termination. There are problems with initialization, creating and destroying threads and semaphores, and using the semaphores for thread communication. Initialization Both the handles for the thread and the semaphore aren't initialized. The logic of Initilize (check spelling) looks flawed. If the call to CreateSemaphore is sucessful (which should be checked) then the handle returned is non-null. In that case Release is called which then closes the handle just created but does not reset the variable. So it looks like the program starts off with a bogus handle to an invalid semaphore. Release() will try to close the threadHandle, which was never initialized, and loses access to the thread without knowing if it ever started or terminated properly. So at the end of a call to Release, assuming that CloseHandle does not raise an exception, threadHandle is invalid. Release is called after every unsuccessful call to CreateThread and threadHandle is invalid (NULL). So Release should be closing an invalid handle which should raise an exception. Semaphore management Assuming the initialization issues are dealt with, we can look at how the semaphore is managed. The semaphore is a "count up" value that signals when non zero. The semaphore is created in the non signaled state. Each thread begins by waiting until the semaphore is signaled and only then calls ReleaseSemaphore which increments the semaphore count and signals any other waiting threads. So the first thread will block on the sempahore. So will the second amd every other thread will because the sempahore was created in the non-signaled state. All threads wait for other threads to end and nobody ends. Thread management The StartSimulation is pretty flawed. The infinite loop and WaitForSingleObject with INFINITE time are problems waiting to happen. The exit condition for the while loop is when the counter variable reaches 100. The counter is incremented every time an attempt to create a thread is made. Attempts to create a thread are controlled by the limit variable. While it is less than maxNumberOfThreads threads are created. As each thread ends, limit is decremented. Since no thread will ever end due to the semaph
-
The problems in the code are various. There are problems with basic thread and semaphore managment. I have to guess at what the code is trying to do: create up to 20 simultaneous threads and wait until until a maximum of 100 threads have been created. Each thread uses a semaphore to block thread termination. There are problems with initialization, creating and destroying threads and semaphores, and using the semaphores for thread communication. Initialization Both the handles for the thread and the semaphore aren't initialized. The logic of Initilize (check spelling) looks flawed. If the call to CreateSemaphore is sucessful (which should be checked) then the handle returned is non-null. In that case Release is called which then closes the handle just created but does not reset the variable. So it looks like the program starts off with a bogus handle to an invalid semaphore. Release() will try to close the threadHandle, which was never initialized, and loses access to the thread without knowing if it ever started or terminated properly. So at the end of a call to Release, assuming that CloseHandle does not raise an exception, threadHandle is invalid. Release is called after every unsuccessful call to CreateThread and threadHandle is invalid (NULL). So Release should be closing an invalid handle which should raise an exception. Semaphore management Assuming the initialization issues are dealt with, we can look at how the semaphore is managed. The semaphore is a "count up" value that signals when non zero. The semaphore is created in the non signaled state. Each thread begins by waiting until the semaphore is signaled and only then calls ReleaseSemaphore which increments the semaphore count and signals any other waiting threads. So the first thread will block on the sempahore. So will the second amd every other thread will because the sempahore was created in the non-signaled state. All threads wait for other threads to end and nobody ends. Thread management The StartSimulation is pretty flawed. The infinite loop and WaitForSingleObject with INFINITE time are problems waiting to happen. The exit condition for the while loop is when the counter variable reaches 100. The counter is incremented every time an attempt to create a thread is made. Attempts to create a thread are controlled by the limit variable. While it is less than maxNumberOfThreads threads are created. As each thread ends, limit is decremented. Since no thread will ever end due to the semaph
Given the above, we change to code to get the program to run. N.B. make sure you compile the code as a multi-threaded app.
const long MAXTHREADS = 100L; const long MAXACTIVETHREADS = 20L; int nThread = 0; int nReleased = 0; long lActiveThreads = 0L; long lPreviousCount = 0L; HANDLE hSemaphore = 0; HANDLE hThread = 0; const char *pSemaphoreName = "CreateThreadSemaphore"; bool Initialize() { bool bResult = false; hSemaphore = ::CreateSemaphore(NULL, 0, MAXACTIVETHREADS, pSemaphoreName); bResult = (0 != hSemaphore); if (!bResult) { // TODO: report error from GetLastError() } return bResult; } DWORD WINAPI Start( LPVOID lpParam ) { // block til semaphore signals ::WaitForSingleObject(hSemaphore, INFINITE); printf("End thread %d\n", GetCurrentThreadId()); --lActiveThreads; ++nReleased; ::ReleaseSemaphore(hSemaphore, 1, &lPreviousCount); return TRUE; } void StartSimulation() { while (nThread < MAXTHREADS) { if (lActiveThreads < MAXACTIVETHREADS) { DWORD dwThreadID = 0; hThread = ::CreateThread(NULL, 0, Start, NULL, 0, &dwThreadID); if (!hThread) { // TODO: report error from GetLastError() } else { printf("Start thread %d\n", dwThreadID); ::CloseHandle(hThread); // throw away thread handle ++lActiveThreads; ++nThread; } } else { ::ReleaseSemaphore(hSemaphore, 1, &lPreviousCount); } } // wait for all threads to end while (lActiveThreads) { ::ReleaseSemaphore(hSemaphore, 1, &lPreviousCount); } // destroy hSemaphore ::CloseHandle(hSemaphore); printf("Created %d threads.\n" "Release %d threads.\n" "PreviousCount %ld\n", nThread, nReleased, lPreviousCount); } int main() { if (Initialize()) StartSimulation(); return 0; }
I changed variable names and removed unnecessary code but didn't implement all the changes I indicated. The output should give you some idea of how running threads behave.