Thread: Problem using "cin" in a thread function?

  1. #1
    Registered User
    Join Date
    Nov 2003
    Posts
    2

    Problem using "cin" in a thread function?

    Hello,

    I have been working on a multithreaded program, and am trying to pass in a value from user input. The problem I an encountering is that the program will not stop to ask for user input if I include the cin in the thread function. It will simply complete the program and goto the "Press any key when ready" message.

    Whereas, if I include the cin in the main() function, it will stop, and ask for user input - but I do not know how to synchronize it so that I can use it in the thread function.

    Here's a snippet of what I have in the thread function:
    Code:
    	
    void egg_funct()
    {
    
    ...
    
    if(requestMutexOrSemaphore(EGG) == TRUE)
    	{
    		cout << "Enter Selection: ";
    		cin >> selection;
    
    	switch (selection)
    	{
    		case 1 ...
                                    ...
    	}
    }
    And the thread code:
    Code:
    egg_thread = CreateThread(
                    NULL,
    		0,
    		(LPTHREAD_START_ROUTINE) egg_funct,
    		(LPVOID) NULL,
    		CREATE_SUSPENDED,	
    		&eggID);
    And in the main() I simply added a cin >> selection - which then causes the program to stop and ask for input. If the cin >> selection was not in the main() function, it'll perform as described above, complete and finish the program without asking for user input.

    The ouput, however, with the cin >> selection added in the main() function is a bit quirky. It in fact asks for user input twice, and does nothing the second time.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Your main() thread could be exiting - destroying all other threads in your process. Or you never resume your thread. Since you created it with the CREATE_SUSPENDED flag, your thread will not run until you call ResumeThread().
    Here is a simple example of running and waiting on a thread.
    Code:
    #include <windows.h>
    #include <iostream>
    using namespace std;
    
    
    DWORD WINAPI thread_function(LPVOID param)
    {
        for (int n = 0; n < 3; n++)
        {
            cout << "Look at me!, I'm a thread with id = " << GetCurrentThreadId()
                 << endl << flush;
            Sleep(750);
        }//for
    
        DWORD ret;
        cout << "Now give me a value to return: ";
        cin >> ret;
    
        return ret;
    }//thread1
    
    
    int main()
    {
        DWORD thread_id;
        HANDLE hthread = CreateThread(NULL, 0, thread_function, NULL, 0, &thread_id);
        if (hthread == NULL)
        {
            cout << "CreateThread() failed, last error = " << GetLastError() << endl;
            return 1;
        }//if
    
        // wait for thread to complete
        WaitForSingleObject(hthread, INFINITE);
    
        // get the exit code for the thread
        DWORD ret;
        GetExitCodeThread(hthread, &ret);
    
        cout << "Thread returned: " << ret << endl;
    
        return 0;
    }//main
    Be sure you are linking against the multithreaded versions of the standard library as well.

    gg

  3. #3
    Registered User
    Join Date
    Nov 2003
    Posts
    2
    Hey Codeplug,

    You were right, the main() was exiting and killing all the threads. I added a WaitForSingleObject() function and now the cin works great.

    But now I have another problem. I have a semaphore that I released using ReleaseSemaphore(Handle, 1, 0). The use of this semaphore is to be recycled as a signal to my chicken thread to release another egg. The chicken cannot release another egg if an egg is already being released. Once an egg has been released, it will signal the chicken thread, and the chicken can then release another egg. The problem I'm having is that the egg semaphore won't decrement, therefore the WaitForSingleObject(egg_sem, INFINITE) function hangs.

    Here is code for releasing the egg semaphore, to indicate an egg has dropped.
    Code:
    	if(ReleaseSemaphore(egg_sem, 1, 0) == NULL)
    		cout << "Egg Error" << endl;
    	else
    	{
    		ReleaseSemaphore(egg_sem, 1, 0);
    		cout << "Egg Released" << endl;
    	}
    Which thread should be waiting for the egg semaphore to return back to zero? And how does the function WaitForSingleObject() decrement the count? I've read on the MSDN site that "count decremented by 1 when wait function releases a thread waiting for the semaphore." I'm confused as to how this is actually implemented.

    I hope this makes sense. Thanks.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> if(ReleaseSemaphore(egg_sem, 1, 0) == NULL)
    ReleaseSemaphore() returns BOOL, so compare with TRUE or FALSE.

    >> ReleaseSemaphore(egg_sem, 1, 0);
    Now you've called it twice, incrementing the semaphore's count again.

    You create a Win32 semaphore with an initial count. This count basicly represents the number of times WaitForSingleObject() can be called before it blocks. Each time WaitForSingleObject() is called, the count on the semaphore is decremented. If this count is zero then WaitForSingleObject() will block until the count is incremented (releasing a single thread waiting on the semaphore). You call ReleaseSemaphore() to increment the count.
    Here's another simple example:
    Code:
    #include <windows.h>
    #include <iostream>
    using namespace std;
    
    HANDLE g_sema;
    
    DWORD WINAPI thread_function(LPVOID param)
    {
        cout << "Releasing g_sema in " << flush;
        for (int n = 5; n > 0; n--)
        {
            cout << n << " " << flush;
            Sleep(1000);
        }//for
        cout << endl;
    
        ReleaseSemaphore(g_sema, 1, NULL);
    
        return 0;
    }//thread1
    
    int main()
    {
        g_sema = CreateSemaphore(NULL, 2, 2, NULL);
        if (g_sema == NULL)
        {
            cout << "CreateSemaphore() failed, last error = " << GetLastError() << endl;
        }//if
    
        DWORD thread_id;
        HANDLE hthread = CreateThread(NULL, 0, thread_function, NULL, 0, &thread_id);
        if (hthread == NULL)
        {
            cout << "CreateThread() failed, last error = " << GetLastError() << endl;
            return 1;
        }//if
    
        // count for g_sema will be 1 after call
        WaitForSingleObject(g_sema, INFINITE);
        
        // count for g_sema will be 0 after call
        WaitForSingleObject(g_sema, INFINITE);
        
        // this call will block until other thread makes count non-zero
        WaitForSingleObject(g_sema, INFINITE);
    
        cout << "here!" << endl;
    
        // wait for thread to complete (we all know how to spell "ass-u-me")
        WaitForSingleObject(hthread, INFINITE);
    
        // forgot to do this in my last past
        CloseHandle(hthread);
        CloseHandle(g_sema);
    
        return 0;
    }//main
    gg

  5. #5
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    It sounds like you have one chicken thread which lays eggs and one or more handler threads that handle the newly laid eggs. I gather you don't want the chicken to lay until a handler thread is available to deal with it.

    If this is the case:
    Create the semaphore with its initial count set to the number of handler threads.

    Then you only want the chicken to lay if a handler thread is available so wait on the semaphore before laying.
    - If the semaphore's count is zero(meaning that no handler threads are available) this will block until the count is greater than zero(meaning that a handler thread is available).
    - This will decrement the semaphore's count(meaning that one less handler thread is available).
    WaitForSingleObject(egg_sem, INFINITE);

    Once the handler thread has handled the egg we want to indicate that the handler thread is available again so we increment the semaphore's count:
    Code:
    if(!ReleaseSemaphore(egg_sem, 1, NULL) )
    	cout << "Egg Error" << endl;
    else
    	cout << "Egg Released" << endl;
    NOTE: Don't release the semaphore twice.

    If the chicken was waiting on the semaphore, it will now be released to do its stuff.

    A semaphore is designed to control access to a finite resource. In this case it is handler threads. The chicken will only lay while a handler thread is available and will pause if none is available.

    EDIT: BEATEN! Read CodePlug's better description.
    Last edited by anonytmouse; 11-24-2003 at 09:11 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. DLL Function / Load Library Problem
    By cboard_member in forum Windows Programming
    Replies: 5
    Last Post: 12-10-2005, 10:11 AM
  2. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  3. Replies: 6
    Last Post: 03-02-2005, 02:45 AM
  4. structure vs class
    By sana in forum C++ Programming
    Replies: 13
    Last Post: 12-02-2002, 07:18 AM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM