Thread: Having only one function run at higher priority

  1. #1
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582

    Having only one function run at higher priority

    I would like my timer function, which uses the Windows multimedia timer, to run at a higher-than-normal priority. I want the main program itself to run at normal priority but the timer function (and only this function) to run at high priority. How can this be done, if it's possible?

    As a side note (clues) I've noticed that, as background tasks run, the timer slows down and the more CPU usage the background tasks have (all at normal priority), the slower the timer gets to nearly stopped when 95% CPU usage is present (at 95% usage, it takes 20 seconds for 1 second to show in the timer). Run my program from the IDE and it's smooth motion. If I switch to Windows Task Manager (which averages 7% CPU usage) then to my program while still running, a "jerk" occurs roughly 3 times a second due to the timer being slower than it should be.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  2. #2
    pwns nooblars
    Join Date
    Oct 2005
    Location
    Portland, Or
    Posts
    1,094
    You could thread it off and give the thread higher priority, then just have the main program request the time from the other thread. But that sounds like it would be overkill.

  3. #3
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    I'm confused as to what you're saying. Could you explain? And why would it be overkill? This is a game so CPU usage is generally expected to be a bit high. It's only this one thread that has it as well. Everything except the rather short timer function should be of normal priority, like most every other program does. As I have it, it hovers around 45% CPU usage (the ground has a fairly large impact, considering I'm not using hardware acceleration all that much).
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  4. #4
    pwns nooblars
    Join Date
    Oct 2005
    Location
    Portland, Or
    Posts
    1,094
    It is just that threading can take a lot of work to get working properly and introduce hard to find bugs. Assuming (from your sig and talk of tasks manager) you are developing on and for windows xp, look up CreateThread

  5. #5
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Is there something that works with Windows 98? I'm developing to at least have support for Windows 98 at the earliest. It's a fairly simple 2D game that could work well on the rather outdated OS, especially with the graphics settings toned down a bunch, mainly visibility and visibility range. CreateThread only goes to 2000.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  6. #6
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    Windows 98 Programming (Schildt) page 538 says you can use GetPriorityClass() and SetPriorityClass().

    DWORD GetPriorityClass(HANDLE hApp) ;

    BOOL SetPriorityClass(HANDLE hApp, DWORD dwPriority) ;

    dwPriority can be (highest to lowest):
    • REALTIME_PRIORITY_CLASS
    • HIGH_PRIORITY_CLASS
    • NORMAL_PRIORITY_CLASS
    • IDLE_PRIORITY_CLASS

    Programs get NORMAL_PRIORITY_CLASS by default.

    And then there are Get & SetThreadPriority().

    Todd
    Mainframe assembler programmer by trade. C coder when I can.

  7. #7
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    This appears to affect the entire program when I only want one single function to have this. I want this special function to be of "high priority class" (for timers, this is especially useful) and the rest of the program (the scene drawing, movement, text-displaying, etc.) to be at the "normal priority class". What function is there that would create a thread for only this one function and work with Windows 98? Basically, this is what is supposed to happen:

    1. Update timer, incrementing until roughly one frame's span has passed (16.667 ms; high priority)
    2. Let other high-priority tasks run.
    3. Process control inputs (such as the left arrow key being used to go left; normal priority)
    4. Update positions of the images (more distant objects appear to move more slowly; normal priority)
    5. Draw the scene into the back buffer (from furthest to closest; normal priority)
    6. Process and draw text (such as updating digits to indicate score; normal priority)
    7. Blit the two buffers (copy the back buffer into the front buffer and draw it on screen; normal priority)
    8. Let other normal and lower priority tasks run.
    9. Update timer for the next frame (advancing another 16.667 ms)
    ... and so on until the program closes.

    I may have omitted something, but this is the basic idea of I want.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  8. #8
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    MM timers could work on threads - so thread priority thing could be applied
    If you do not want to work with threads - what mechanism of MM timers you are using?

    for example if you are working with windows MM_XXX messages (which methid by itself inplies some overhead) you can in your message loop add PeekMessage with the range including only MM timers messages - and if they are available - process them befoe other messages - if not - call GetMessage in a regular way
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  9. #9
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    From what you've described I'm quite sure that your windows message processing loop isn't written how it should be for a real-time game. You need to make sure that you process ALL messages in the queue each time, until there are none left, not just the one. Counterintuitively, this actually makes it run much smoother even though you'd think it would do the opposite.

    Can you post your Message loop then? That's the function with the PeekMessage in it.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #10
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    I actually don't use Windows messaging for the timer (or even for much of anything at all). The only thing the Windows messaging system is even used for are those 3 buttons at the top right corner of any window - minimize, maximize, and, most importantly, close. Close first terminates the main loop by setting a variable to make the loop false, then all resources and malloced memory is freed after right before closing. This is my full timer code. It's the second function that I want at high priority, not the first. The first is called on startup and is never called again. Read the function description comments at the top for details.

    Code:
    void PrepareClock()
    {
    	/*
    	This function sets up the timer using the finest timing resolution possible.
    	It is called on startup and should be of normal priority.
    	*/
    	
    	int LoopCount = 0;
    	
    	CurrentTime = timeGetTime();
    	Actual = CurrentTime;
    	Offset = 0;
    	
    	while (timeBeginPeriod(TimerDelay) == TIMERR_NOCANDO) // loop until no error is encountered
    	{
    		if (LoopCount >= 100)
    		{
    			// infinite loop warning stuff
    		}
    		
    		timeEndPeriod(TimerDelay); // terminate for another attempt at it
    		TimerDelay++; // increment until no error occurs
    		RangeLimit += 1.0; // increase the range limit as well, used for the offsets
    		LoopCount++;
    	}
    }
    
    ... // other code
    
    void AdvanceClock()
    {
    	/*
    	This function advances the timer/clock to get as close as possible to 60 fps, the refresh rate of my monitor.
    	It should be adjusted to allow for different refresh rates, like 75 fps.
    	It should also be on a separate, a separate, high-priority thread to eliminate jerking and inaccuracies.
    	Without this, the clock runs slower than it should causing jerks, even if only 5% BG CPU usage is used.
    	*/
    	
    	int LoopCount = 0;
    	Actual += 16.66666666666667; // increment for 60 fps // make variable based on config settings
    	
    	Offset = CurrentTime - Actual; // find the offset
    	
    	while (Offset < 0.0) // if not long enough of a delay
    	{
    		if (LoopCount >= 1000)
    		{
    			// infinite loop warning indicators
    		}
    		
    		Sleep(1); // wait a little longer
    		CurrentTime = timeGetTime(); // reobtain the time
    		Offset = CurrentTime - Actual; // and the offset
    		LoopCount++;
    	}
    	
    	while (Offset > (16.66666666666667+RangeLimit)) // excessively long delay (as from sudden stalls due to sudden CPU usage)
    	{
    		MoveObjects(); // to prevent sudden stopping when CPU usage is up a bit
    		ProcessInput();
    		
    		Actual += 16.66666666666667; // boost the actual time to keep in sync
    		CurrentTime = timeGetTime(); // reobtain the clock
    		Offset = CurrentTime - Actual; // and the offset
    	}
    }
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  11. #11
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Sleep(1); // wait a little longer
    It is definitely NOT the best resolution possible on the Windows

    Where are the MM timers you talked about?
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    This is actually win32 API discussion, not a C discussion.

    It is possible to set the priority of a thread using SetThreadPriority(). That really only works well if that worker thread only communicates occasionally with the main thread (eg if the worker thread at higher priority is forced to wait on the application main thread, then a priority inversion can occur -- or the windows scheduler boosts priority of the main thread to match that of the worker thread). It can also cause real problems if the higher priority thread uses large amounts of CPU time, as it can starve other threads.

    Hence a need to test your code very carefully if doing this sort of thing.

  13. #13
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    The multimedia timer is there. Note the use of timeGetTime(). I didn't think that this was strictly Windows-related stuff knowing that threads are common in many programs. Most programs I see typically have 3 or more threads, one even has 68. My program currently has only one. Since this thread seems to have geared toward Windows development instead, I would agree that it should be moved to the Windows forum instead of just here.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  14. #14
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    this function has nothing to do with MM timers
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  15. #15
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    Then what is the "timeGetTime", "timeBeginPeriod", and "timeEndPeriod" all about? I checked the Windows Platform SDK documentation and searching "timeGetTime", I see "multimedia timers" in the list and an assortment of links that goes straight to this. This means that I am using multimedia timers, MM timers. Browse through this area and you'll see what I mean.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Change this program so it uses function??
    By stormfront in forum C Programming
    Replies: 8
    Last Post: 11-01-2005, 08:55 AM
  2. const at the end of a sub routine?
    By Kleid-0 in forum C++ Programming
    Replies: 14
    Last Post: 10-23-2005, 06:44 PM
  3. Run function from text file
    By hendraiskandar in forum C Programming
    Replies: 1
    Last Post: 06-20-2005, 01:36 AM
  4. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  5. Replies: 5
    Last Post: 02-08-2003, 07:42 PM