Click here to Skip to main content
15,940,430 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm trying to code a timeout function that kicks out the user if he doesn't select any options in a given amount of time. However I'm finding myself stuck in a infinite loop and even my wait timer can't destroy the loop.

My code:
namespace jsw {
    namespace threading {
        class auto_event {
        public:
            auto_event() : _event(CreateEvent(0, false, false, 0)) {}

            BOOL wait(DWORD timeout = 1) const
            {
                return WaitForSingleObject(_event, timeout) == WAIT_OBJECT_0;
            }

            BOOL set() { return SetEvent(_event); }
            BOOL reset_event() { return ResetEvent(_event); }
        private:
            HANDLE _event;
        };

        class thread {
        public:
            static thread start(
                LPTHREAD_START_ROUTINE fn, LPVOID args = 0,
                DWORD state = 0, DWORD timeout = 5000)
            {
                return thread(CreateThread(0, 0, fn, args, state, 0), timeout);
            }

            static void sleep(DWORD milliseconds) { Sleep(milliseconds); }
            static void exit(DWORD exitCode) { ExitThread(exitCode); }
        public:
            thread(HANDLE thread, DWORD timeout) : _thread(thread), _timeout(timeout) {}
            ~thread() { CloseHandle(_thread); }

            DWORD exit_code() const
            {
                DWORD exitCode = NO_ERROR;

                GetExitCodeThread(_thread, &exitCode);

                return exitCode;
            }

            HANDLE handle() const { return _thread; }
            BOOL is_alive() const { return exit_code() == STILL_ACTIVE; }
            DWORD join() { return WaitForSingleObject(_thread, _timeout); }
            DWORD suspend() { return SuspendThread(_thread); }
            DWORD resume() { return ResumeThread(_thread); }
            BOOL abort(DWORD exitCode) { return TerminateThread(_thread, exitCode); }
        private:
            HANDLE _thread;
            DWORD _timeout;
        };
    }
}


DWORD WINAPI get_option(LPVOID args)
{
    using namespace jsw::threading;

    int* option = (int*)((LPVOID*)args)[0];
    auto_event* e = (auto_event*)((LPVOID*)args)[1];

    std::cin >> *option;
    e->set();

    return NO_ERROR;
}

int main()
{
    using namespace jsw::threading;

    int option{};
    auto_event e;
    LPVOID args[2] = { &option, &e };

    thread worker = thread::start(get_option, args);

    if (e.wait(5000)) {
        do {
            system("cls");

            switch (option) {
            case 1: // Do some stuff...
                break;
            case 2: // Do some stuff...
                break;
            case 3: // Exit
                break;
            default: std::cout << "Option not valid!" << std::endl;
                break;
            }
        } while (option != 3);
        std::cout << "***Program Exit***" << std::endl;
    }
    else {
        worker.abort(NO_ERROR);
        std::cout << "***PROGRAM END***\n";
    }
}


What I have tried:

I managed to make the loop work in the get_option function; however I had a problem with the timeout function since it couldn't work in it, so I decided to put the loop in the main function, yet nothing works.

So if possible can somebody tell me how to fix this infinite loop and the timer?
Posted
Updated 27-Mar-23 9:54am
Comments
Mircea Neacsu 27-Mar-23 14:20pm    
Creating a thread in the constructor of an object is VERY dangerous. Take a look at my article about threads and objects[^]. You can borrow a thread object from there.
RexyCode 27-Mar-23 15:16pm    
Your article was a nice read; however I don't exactely know how to proceed with your threads, should I use the code from the mlib/thread.h library or another piece of code?
In addition would the timeout function still be able to do its job?
Lastly is there any other problem with my code apart from the constructor?
I am still a newbie programmer so I'm sorry for all the questions.
Mircea Neacsu 27-Mar-23 15:32pm    
Yes, you can just get thread.h/cpp and related files (event.h/cpp, syncbase.h/cpp).

Still looking at your code and trying to figure out if there are other problems
RexyCode 29-Mar-23 14:36pm    
I tried your code, and unfortunately it doesn't work, we can only use the get_option function once and after entering a value we are stuck in an infinite loop ("Timeout!" continues to get printed out).
I appreciate the help nonetheless.

1 solution

The wait function is OK. It's the main loop logic that is not right. The do...while loop has nothing to break it as the wait function is outside the loop.

This should work:
C++
int main ()
{
  using namespace jsw::threading;

  int option{};
  auto_event e;
  LPVOID args[2] = { &option, &e };

  thread worker = thread::start (get_option, args);

  system ("cls");
  do {
    if (e.wait (5000))
    {
      switch (option) {
      case 1: // Do some stuff...
        break;
      case 2: // Do some stuff...
        break;
      case 3: // Exit
        break;
      default: std::cout << "Option not valid!" << std::endl;
        break;
      }
    }
    else
    {
      std::cout << "Timeout!" << std::endl;
      option = 0; //timeout while waiting - what should we do?
    }
  } while (option != 3);
  std::cout << "***Program Exit***" << std::endl;
  worker.abort (NO_ERROR);
  std::cout << "***PROGRAM END***\n";

}
 
Share this answer
 
v2
Comments
RexyCode 28-Mar-23 10:41am    
I tried your code, and unfortunately it doesn't work, we can only use the get_option function once and after entering a value we are stuck in an infinite loop ("Timeout!" continues to get printed out).
I appreciate the help nonetheless.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900