Thread priority?

Hello.
I am not sure if it’s ontopic. It’s about threads, but I am going to use
threads in SDL.

I am writting helicopter simulator (http://decopter.sf.net). I am working with
terrain rendering, now.

I want to have very big landscape. Not just 2048x2048, but for example many
blocks of size 1024x1024.
I need to draw only a few (9, 25, 49) blocks at once. I don’t want to store in
RAM whole data (it’s not only height map, but also ROAM variance trees), so -
when I move from place to place - sometimes new blocks are needed.
Let’s say I draw 7x7 blocks. I am crossing a line, and 7 new blocks are needed.
Now - in just one frame - I must calculate 7 heightmaps and other related data.
Game will stop for a while. I don’t want it.

So I am thinking about “cache”. I need 49 blocks, but I will store 100 blocks
in cache. I must have another thread which will slowly calculate at least
99-77 blocks, so when I cross the line - blocks will be ready in cache.

I know how to start thread. But how can I set thread priority? I must be sure,
that blocks calculating thread do not takes half of CPU, it must be very slow.

I thought about loop:

  • calc part of data
  • SDL_Delay(100)

But is there a better solution?

I know how to start thread. But how can I set thread priority? I must be sure,
that blocks calculating thread do not takes half of CPU, it must be very slow.

I thought about loop:

  • calc part of data
  • SDL_Delay(100)

But is there a better solution?

Nope, that’s the best portable way to do this.

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment

— Jacek Pop?awski wrote:

I know how to start thread. But how can I set thread
priority? I must be sure,
that blocks calculating thread do not takes half of
CPU, it must be very slow.

I thought about loop:

  • calc part of data
  • SDL_Delay(100)

But is there a better solution?

The best general solution is exactly that, but I think
a better solution is to take into account how long the
calculations HAVE taken and when they NEED to be done
(with a small comfort-zone to accomidate scheduling
inconsistancies)… You might even want to spin a
seperate thread for each block, and have each thread
pace itself against when it needs to be done. This
may make the program run better on multi-CPU machines.

Maybe something like:

typedef struct {
float estimated_time_until_needed;
/* <0 means needed now /
uint chunks_calculated;
MapBlockData
pData;
} BlockCacheData;

enum { CHUNKS_PER_BLOCK = 256 };
enum { CACHE_SIZE = 128 };

BlockCacheData block_cache[CACHE_SIZE];

int StartCalculateThread(void* pVoidQuitThread)
{
bool* pQuitThread = (bool*)pVoidQuitThread;
uint i;
for(i=0; i < CACHE_SIZE; i++)
{
block_cache[i].pData = NULL;
block_cache[i].chunks_calculated =
CHUNKS_PER_BLOCK;
}
while(!(pQuitThread))
{
update_estimated_time_until_needed();
BlockCacheData
pSortedBlocks[CACHE_SIZE];
uint SortedBlocksNeedingUpdate;
sort_blocks_needing_update(pSortedBlocks,

                      &SortedBlocksNeedingUpdate);

#if ASSERTS_ENABLED
assert(SortedBlocksNeedingUpdate <=
CACHE_SIZE);
for(
i=0;
i < SortedBlocksNeedingUpdate;
i++
)
{
assert(pSortedBlocks[i]->chunks_calculated
< CHUNKS_PER_BLOCK);
assert((i==0) ||
(pSortedBlocks[i-1]->estimated_time_until_needed <=
pSortedBlocks[i]->estimated_time_until_needed);
}
#endif /* ASSERTS_ENABLED */

    uint TotalChunksNeeded=0;
    uint MinimumMsecPerChunk = 500;
    /* Maximum sleep time 500 msec */
    for(
        i=0;
        (i < SortedBlocksNeedingUpdate) &&

(MinimumMsecPerChunk > 0);
i++
)
{
TotalChunksNeeded += CHUNKS_PER_BLOCK -
(pSortedBlocks[i]->chunks_calculated);
assert(TotalChunksNeeded);
uint Rate =
(pSortedBlocks[i]->estimated_time_until_needed * 1000
/ pTotalChunksNeeded);
if( Rate < MinimumMsecPerChunk)
{
MinimumMsecPerChunk = Rate;
}
}
uint MsecToSleepAfterCalcs =
MinimumMsecPerChunk;
if( TotalChunksNeeded )
{
uint CalculationsMade = 0;
ulong StartTime = SDL_GetTicks();
do {
calculate_chunk();
CalculationsMade++;
TotalChunksNeeded–;
} while ((TotalChunksNeeded > 0) &&
(CalculationsMade < CHUNKS_PER_BLOCK) &&
((SDL_GetTicks() - StartTime) > (CalculationsMade *
MinimumMsecPerChunk))) ;
if ((SDL_GetTicks() - StartTime) >
(CalculationsMade * MinimumMsecPerChunk))
{
MsecToSleepAfterCalcs = 0 ;
}
else
{
MsecToSleepAfterCalcs =
((CalculationsMade * MinimumMsecPerChunk) -
(SDL_GetTicks() - StartTime)) ;
}
}
SDL_Delay(MsecToSleepAfterCalcs)
}
}

This is alot more complex than

  • calc part of data
  • SDL_Delay(100)

but it should auto-throttle with load…

(Hmmm… now that I’ve written all that code, I wonder
if the original solution would have been better…)

Hope that helps,

-Loren__________________________________________________
Do You Yahoo!?
Yahoo! Health - Feel better, live better