Interrupt handling very slow

Started by
9 comments, last by SeanMiddleditch 9 years, 8 months ago

Hi,

when I scroll very fast, I have the problem that the interrupt handling is too slow. When I scroll in the opposite direction, it takes a long time (up to some seconds) until the camera moves in the opposite direction. Does anyone knows how to solve this issue?


LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
    switch(umessage)
    {
        // Check if the window is being destroyed.
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }

        // Check if the window is being closed.
        case WM_CLOSE:
        {
            PostQuitMessage(0);        
            return 0;
        }

        

        // All other messages pass to the message handler in the system class.
        default:
        {
            return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
        }
    }
}

LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
    if(umsg == WM_MOUSEWHEEL)
        {
            //MessageBox(m_hwnd, L"Mouse wheel", L"Test", MB_OK);
            

            short x = (short)HIWORD(wparam);
            m_Application->HandleInterrupt(MOUSEWHEEL_ROTATED,x);
 
        }
    return DefWindowProc(hwnd, umsg, wparam, lparam);
}

void ApplicationClass::HandleInterrupt(int buttonID, int param1){
    //WaitForSingleObject(InterruptMutex,INFINITE);
    if(buttonID==MOUSEWHEEL_ROTATED){
        if(param1<0){
            targetCameraDistance+=0.5f;
            if(targetCameraDistance>=m_settings->maxCameraDistance){
            targetCameraDistance=m_settings->maxCameraDistance;
            }
        }
        if(param1>0){
            targetCameraDistance-=0.5f;
            if(targetCameraDistance<=0){
            targetCameraDistance=0;
            }
        }
    }
    //ReleaseMutex(InterruptMutex);
}

Do I need the Mutex when handling interrupts?

Greetings,

Magogan

Advertisement

I noticed a lot of people make mistake of using if(PeekMessage(&message, 0, 0, 0, PM_REMOVE)) instead of while(...) inside game loop, this might be source of the problem.

No, I just used the WndProc function, but it seems that it is too slow for my purposes. PeekMessage seems to be fast enough. Now it works :D

What has this got to do with handling interrupts? These messages are just dispatched inside your main message loop. There are no interrupts involved so no need for mutexes, no. This is all running in the same thread.

Generally when the problem appears to be that the Windows message queue mechanism is too slow, that is usually not the case at all.

It can only deliver you the next message when you request it, and you normally only request it when you are finished dealing with the current message. So basically your own slow message processing slows down the receipt of further messages.

One mistake I've come across when processing Windows messages is when you only allow at most one Windows message to be processed each time around your main loop, seemingly giving maximum time to the rest of your drawing code. In reality what happens is that this slows the program down horribly. You should endeavour to process ideally all messages before doing any other stuff in your main loop. Although this may be counter-intuitive, it actually makes a world of difference. Give Windows more attention and promptly process its messages, and your program's performance will be greatly rewarded.

Those are not interrupts and no you do not need a mutex there. In fact the term "interrupts" doesn't have much applicability at all in a Windows program. The terms that you need to be familiar with are synchronous / asynchronous, blocking / non-blocking, or single-threaded / multi-threaded.

You can confirm this for yourself by placing a breakpoint within the HandleInterrupt function, and when the breakpoint is hit, examine the Call Stack window. When you can look back through the call stack of the same thread and find the original GetMessage or PeekMessage call, then what your application is doing is entirely synchronous, or blocking.

"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms

Magogan, post the code of your message loop.

That's probably where the problem lies. (As others have pointed out already)

I have fixed the message loop and now it should work.

void SystemClass::Run()
{
    MSG msg;
    bool done, result;


    ZeroMemory(&msg, sizeof(MSG));
    
    done = false;
    while(!done)
    {
        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            
            if(msg.message == WM_QUIT){
                done = true;
            }
            else if(msg.message == WM_MOUSEWHEEL){
                short x = (short)HIWORD(msg.wParam);
                m_Application->HandleInterrupt(MOUSEWHEEL_ROTATED,x);
            }
        }
        else
        {
            
            result = Frame();
            if(!result)
            {
                done = true;
            }
        }

    }

    return;
}

Seems reasonable, although the use of an if-then confused me a bit. Mine looks like:


    while(msg.message != WM_QUIT)
    {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        doGameLoopStuff();
    }

Guess no difference really though.

Why are you manually handling WM_MOUSEWHEEL like that? Does it not get passed to your WndProc like every other message? My concern is you are processing that message twice each time it is issued, based on this and your previous code.

One thing I noticed is that you aren't quite correctly handling the parameter of WM_MOUSEWHEEL.

You're correctly checking for negative or positive values to determine direction, but the value is important too. As the documentation states, the value is in multiples of WHEEL_DELTA, so the larger the value, the larger your response should be. Otherwise the mousewheel will feel slow or laggy as your game doesn't respond to how fast the user is scrolling the wheel.

Btw., you are handling WM_CLOSE wrongly. Instead of calling PostQuitMessage you should call DestroyWindow (which then causes WM_DESTROY message and some other things for cleanup). http://msdn.microsoft.com/en-us/library/windows/desktop/ms632617%28v=vs.85%29.aspx

This topic is closed to new replies.

Advertisement