Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7953 Discussions

Sharing a buffer for read from two or more threads

raulhuertas
Beginner
304 Views

Hello multithreading gurus!

I'm staring working in a graphics engine(not just for games). My idea for increase the multithreading capabilities is to hva de double-buffer(like the garphic one) for the physics, B1 and B2. So when the application start, the render takes tha data form B1, anf the physics(or whatever other think, AI...) also takes the data from B1 but store the results in B2. Finally they are swapped and the process starts again. So, as B1 is just for read, I think it doesn't need any mutex/seamphore trick. I was thinking in use this pseudocode:

struct WorldStatBuffer{

private Mutex mutex;//the mutex for the swap

friend TheUser;

public Data* data; //the data to share, no mutexed

}

WorldStatBuffer b1, b2;

create GraphicsRenderer(b1);

createPhysicsSimulatior(initState = b1, result = b2);

initWorld(b1);

while(continue){

draw();//Async

while(waitTimeStep){

simulate();//aSync

}

swapBuffers();

}

The mutex is just for the swap(), not for acces the data and update it. Of course swap can be atomic. Have anyone work with something like this?. Is there a way to eliminate the mutex from the WorldStateBuffer and put it on the swap call?

0 Kudos
2 Replies
JenniferJ
Moderator
304 Views
If you protect the data with mutex, it would be very slow because every access to the data from every where is one thread only even with read.
You just need to add the mutex/critical section around the code that write/read or write/write to the shared variable in the re-entry functions.
Check OpenMP.org as well.
0 Kudos
jimdempseyatthecove
Honored Contributor III
304 Views

The following is a non-mutex method using 3 buffers where the Simulate alternates between two buffers and can advance faster than draw time (drawing out of third buffer).

Jim Dempsey

[cpp]WorldStatBuffer b[3];

b[0].InitWorld();	// allocate and initialize
b[1] = b[0];		// allocate and duplicates data
b[2] = b[0];		// allocate and duplicates data

volatile int displayFrame = 0;
volatile bool Done = false;

beginThread(Simulate);
beginThread(Draw);
...
// OnCancel:
   Done = true;
...

void Simulate()
{
  enum enumState
  {
    b0b1, b1b0, b0b2, b2b0, b1b2, b2b1
  };
  enumState state = b0b1;

  while(!Done)
  {
    switch(state)
    {
    case b0b1:
      if(displayFrame == 1)
      {
         state = b0b2;
         break;
      }
      AdvanceState(b[0], b[1]);
      state = b1b0;
      if(displayFrame < 0) displayFrame = 1;
      break;

    case b1b0:
      if(displayFrame == 0)
      {
         state = b1b2;
         break;
      }
      AdvanceState(b[1], b[0]);
      state = b0b1;
      if(displayFrame < 0) displayFrame = 0;
      break;

    case b0b2:
      if(displayFrame == 2)
      {
         state = b0b1;
         break;
      }
      AdvanceState(b[0], b[2]);
      state = b2b0;
      if(displayFrame < 0) displayFrame = 2;
      break;

    case b2b0:
      if(displayFrame == 0)
      {
         state = b2b1;
         break;
      }
      AdvanceState(b[2], b[0]);
      state = b0b2;
      if(displayFrame < 0) displayFrame = 0;
      break;


    case b1b2:
      if(displayFrame == 2)
      {
         state = b1b0;
         break;
      }
      AdvanceState(b[1], b[2]);
      state = b2b1;
      if(displayFrame < 0) displayFrame = 2;
      break;

   case b2b1:
      if(displayFrame == 1)
      {
         state = b2b0;
         break;
      }
      AdvanceState(b[2], b[1]);
      state = b1b2;
      if(displayFrame < 0) displayFrame = 1;
      break;
    default:
     }
  }
}

void Draw()
{
   while(!Done)
   {
     DrawFrame(b[displayFrame]);
     displayFrame = -1;
     while(displayFrame < 0)
       sleep(0); // or SwitchToThread();
   }
   
}



[/cpp]

0 Kudos
Reply