Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Managing threads

This thread is locked; no one can reply to it. rss feed Print
Managing threads
shadyvillian
Member #12,426
December 2010

I'm attempting to use c#'s easy threading with allegro's.. well awesomeness. I poll for events on a separate thread, but now I need to draw on another...

I have the reference of a System.Threading.Thread called thread A and I'm on another thread, lets say thread B. Now I need to execute a bit of code on thread A for a moment. Using the reference I have, how can I Invoke thread A to do an action in it?

I'm guessing allegro_bitmap or al_draw_bitmap has a thread affinity.

void AllegroSharp::Display::DrawToBackBuffer(BitmapImage^ image)
{
    al_draw_bitmap(image->GetBitmap(), (float)image->Rect->Position->X, (float)image->Rect->Position->Y, 0);
}

DrawToBackBuffer gets called on thread B and al_draw_bitmap needs to be called on Thread A, which I have a reference to. How can I do this on thread A? Thread B is just some thread that c# spawned when I did a Task.Run in managed code.

Multithreading between c# and Allegro seems to be a little hairy. C# has nice things like dispatcher.invoke to execute a bit of code on a certain thread, then go on its way to what ever its doing. Does anyone have any Insight on what I could do?

c++

#SelectExpand
1EventArgs^ AllegroSharp::Display::WaitForEvent() 2{ 3 ALLEGRO_EVENT event; 4 5 al_wait_for_event(eventQueue, &event); 6 7 switch(event.type) 8 { 9 case ALLEGRO_EVENT_DISPLAY_CLOSE: 10 return gcnew DisplayClosedEvent(); 11 case ALLEGRO_EVENT_TIMER: 12 { 13 if(event.timer.source == timer) 14 { 15 return gcnew TimerEvent(); 16 } 17 } 18 } 19 20 return gcnew EventArgs(); 21}

C#

#SelectExpand
1private void WatchDisplayEvents() 2 { 3 Task.Run(() => 4 { 5 while (IsRunning) 6 { 7 var ev = mainDisplay.WaitForEvent(); 8 9 if (ev != null) 10 { 11 if (ev is DisplayClosedEvent) 12 { 13 OnCloseButtonPressed?.Invoke(this, (DisplayClosedEvent) ev); 14 Console.WriteLine("X button pressed"); 15 } 16 17 else if (ev is TimerEvent) //update the display 18 { 19 lock (backbufferLock) 20 { 21 BitmapImage backbuffer = new BitmapImage(Camera); 22 23 BackBufferImages.Sort((img1, img2) => img1.Layer.CompareTo(img2.Layer)); //sort images by layer so the high indices are drawn on the top 24 25 foreach (var image in BackBufferImages) //piece together an image. then clip it to the size of the screen 26 { 27 if (image.Rect.CollidesWith(Camera)) 28 { 29 backbuffer.DrawOn(image, Camera.Position); 30 31 } 32 } 33 34 mainDisplay.DrawToBackBuffer(backbuffer); 35 mainDisplay.UpdateDisplay(); 36 37 BackBufferImages.Clear(); 38 } 39 } 40 } 41 } 42 }); 43 }

Software Engineer by day, hacker by night.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

I'm not sure of the specifics, but each thread has a list of displays created on it. Each display has a list of compatible bitmaps. I believe to draw to a certain display, or using a certain display's hardware acceleration, you need to draw on the same thread that the display was created on. And all the bitmaps drawn need to be compatible with that display otherwise software drawing will take place.

Can you separate all your drawing onto a single thread? That also creates your display and all of its bitmaps? And then send signals to that thread through a condition variable that signals when to draw?

shadyvillian
Member #12,426
December 2010

Currently when I draw, my app just crashes and dies without warning when I call al_draw_bitmap, as shown in my previous post. My first hunch was the thread affinity. Maybe I'll just devise a nice wrapper around allegro's threading... hmm.

Software Engineer by day, hacker by night.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Are you able to draw on your C#'s main function?

I don't think a wrapper around Allegro's threads will help you here. I'm pretty sure you have to keep drawing on the same thread that created the display.

EDIT
@SlimShady
Have you made any progress?

Go to: