Pergunta

At the moment I am using a producer consumer model for the rendering portion of a realtime graphics application. The consumer will continually look for data in our queue(infinite loop); however I am fearful that this may cause my simulation to get out of sync of the main loop. I think this is the fast producer slow consumer problem - compounded by the fact that the simulation is restrained to a certain amount of time.

Question - what is the best method to keep this all in balance and make sure the consumer has enough time to finish, but also that the simulation does not move to the next frame before we are finished rendering our current frame(or at least be able to detect this and skip rendering the next frame - or interrupt the current frame being rendered) I am currently just interrupting and joining after each consumer is finished

Second Question: if you look at the code below you will see that I am currently just calling interrupt and join after adding rendering jobs to the queue - this allows the thread all the time it needs to complete its operation, and to respond to the interrupt when finished. How can I then reuse threads in a thread pool after interrupt_all and join_all are called? (i.e. if i call drawNextFrame again)

The producer is part of the main thread of execution (I don't think this affects anything)

pseudo code:

void renderSystem::init()
create queue to hold work;
create consumer threads of type RenderConsumer set to watch our queue; 
add threads to thread_pool of consumers called 'RenderThreads'

void renderSystem::drawNextFrame()
for each thread in 'RenderThreads' divy up work; 
add work assignment to queue;
    //RenderThreads will now successfully start pulling data from our queue
renderThreads.interupt_all();
renderThreads.join_all();

int main()
renderer = renderSystem class;
renderer.init()
while(not_gameover)
    renderer.drawNextFrame();
    doOtherCoolStuff();
    profit(?)
return(0)

if you need to look at the consumer class see below:

pseudo code:

RenderConsumer::operator () ()
    while(true)
        try to dequeue from queue
        //digest any packet we get
        for each ( pixel in packet )
            computePrettyStuff()
        //we are now done with packet that we got
        this_thread::interruption_point();

I tried to make this simple and quick to digest, thank you for your time

Foi útil?

Solução

#1. I would do this by counting the amount in the queue after each render. If it too high, then either

a. Dump the queue

b. Set a boolean variable to false That variable will be shared between the threads, and when the producer sees that it is false, it begins waiting on a condition variable. The consumer then notifies the producer when the queue is down to an acceptable level again.

#2. Probably not possible with join_all, as the postcondition to join_all is

Every thread in the group has terminated.

according to the reference.

It might however be possible, using barriers instead of join_all, but then you would have to find a way to provide them data, which would invariably end up needing some more shared variables.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top