|
ALLEGRO_THREAD |
alex glez
Member #16,757
October 2017
|
Hello !. I have a problem with ALLEGRO_THREAD. ------------------------------------------------------------------ static void * SUB(ALLEGRO_THREAD *hilo, void *arg) //************************************************* void GUARDAR_FOTO() if (hilo1 == 0) if (hilo2 == 0) } //**************************************** main ******** for (num_elem=0; num_elem < 100; num_elem++) |
Peter Hull
Member #1,136
March 2001
|
I can't really see how that code would work at all, but.. If it were me I would just split your list of 100 photos into two, and have one thread do the first 50 and one thread do the last 50, then use al_join_thread to wait for them to finish. Does that help?
|
alex glez
Member #16,757
October 2017
|
Hello, thanks for answering, because of the complexity of the program it is impossible for me to separate them into 2 lots, that's why I wanted to split the calls to al_save_bitmap into two execution threads. I need to call a thread to save one bitmap while the other thread goes saving another one simultaneously and when one of them finishes it receives the next bitmap. The program works perfect, I can process more than 1200 photos of 8 mp a day, |
Edgar Reynaldo
Major Reynaldo
May 2007
|
alex glez said: This is a serializing call. This won't work if you want to run them in parallel. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Peter Hull
Member #1,136
March 2001
|
You might want to look at "Thread Pools" or "Producer-consumer queues". It should be possible to find examples using Posix pthreads which is quite close to Allegro's thread API. First though, are sure that your processing is not bound by the time taken to write out to disk? If it is, you won't see much benefit from multithreading.
|
alex glez
Member #16,757
October 2017
|
Yes, the problem is that it runs in series and not in parallel. I do not know how to do it in parallel. I think the processing time is longer than the time needed to write to the disk. My knowledge is very limited, I thought I could do in a simple way two threads in parallel that contain only the "al_save_bitmap" instruction. Could you give me some basic example of how to do it? |
Peter Hull
Member #1,136
March 2001
|
Have a look at: It's a start and hopefully others will suggest a better way to do it.
|
alex glez
Member #16,757
October 2017
|
Thanks to all, the example of the link seems the way forward. I hope to understand ... |
Edgar Reynaldo
Major Reynaldo
May 2007
|
I don't think allegro supports saving bitmaps from a thread other than the one whose display is current. I've got a working ThreadPool, and if I save the bitmaps from the spawned threads, they are black. If I save them from main, they look right. In fact, the GDI save routines fail to acquire a lock on the bitmap to save, so no data is copied to the GDI struct which gets saved. 371bool _al_save_gdiplus_bitmap_f(ALLEGRO_FILE *fp, const char *ident,
372 ALLEGRO_BITMAP *a_bmp)
373{
374 CLSID encoder;
375 int encoder_status = -1;
376
377 if (!_al_stricmp(ident, ".bmp")) {
378 encoder_status = GetEncoderClsid(L"image/bmp", &encoder);
379 }
380 else if (!_al_stricmp(ident, ".jpg") || !_al_stricmp(ident, ".jpeg")) {
381 encoder_status = GetEncoderClsid(L"image/jpeg", &encoder);
382 }
383 else if (!_al_stricmp(ident, ".gif")) {
384 encoder_status = GetEncoderClsid(L"image/gif", &encoder);
385 }
386 else if (!_al_stricmp(ident, ".tif") || !_al_stricmp(ident, ".tiff")) {
387 encoder_status = GetEncoderClsid(L"image/tiff", &encoder);
388 }
389 else if (!_al_stricmp(ident, ".png")) {
390 encoder_status = GetEncoderClsid(L"image/png", &encoder);
391 }
392
393 if (encoder_status == -1) {
394 ALLEGRO_ERROR("Invalid encoder status.\n");
395 return false;
396 }
397
398 AllegroWindowsStream *s = new AllegroWindowsStream(fp);
399 if (!s) {
400 ALLEGRO_ERROR("Couldn't create AllegroWindowsStream.\n");
401 return false;
402 }
403
404 const int w = al_get_bitmap_width(a_bmp), h = al_get_bitmap_height(a_bmp);
405 bool ret = false;
406
407 Gdiplus::Bitmap *gdi_bmp = new Gdiplus::Bitmap(w, h, PixelFormat32bppARGB);
408
409 if (gdi_bmp) {
410 Gdiplus::Rect rect(0, 0, w, h);
411 Gdiplus::BitmapData *gdi_lock = new Gdiplus::BitmapData();
412
413 if (!gdi_bmp->LockBits(&rect, Gdiplus::ImageLockModeWrite,
414 PixelFormat32bppARGB, gdi_lock)) {
415
416 ALLEGRO_LOCKED_REGION *a_lock = al_lock_bitmap(
417 a_bmp, ALLEGRO_PIXEL_FORMAT_ARGB_8888, ALLEGRO_LOCK_READONLY);
418
419 if (a_lock) { 420 unsigned char *in = (unsigned char *)a_lock->data;
421 unsigned char *out = (unsigned char *)gdi_lock->Scan0;
422
423 if (gdi_lock->Stride == a_lock->pitch) {
424 memcpy(out, in, h * gdi_lock->Stride);
425 }
426 else {
427 uint32_t rows = h;
428 while (rows--) {
429 memcpy(out, in, w * 4);
430 in += a_lock->pitch;
431 out += gdi_lock->Stride;
432 }
433 }
434
435 al_unlock_bitmap(a_bmp);
436 }
437 gdi_bmp->UnlockBits(gdi_lock);
438 }
439
440 ret = (gdi_bmp->Save(s, &encoder, NULL) == 0);
441
442 delete gdi_lock;
443 delete gdi_bmp;
444 }
445
446 s->Release();
447
448 return ret;
449}
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
SiegeLord
Member #7,827
October 2006
|
Edgar Reynaldo said: I don't think allegro supports saving bitmaps from a thread other than the one whose display is current. I've got a working ThreadPool, and if I save the bitmaps from the spawned threads, they are black. If I save them from main, they look right. In fact, the GDI save routines fail to acquire a lock on the bitmap to save, so no data is copied to the GDI struct which gets saved. Yeah, that's expected, but perhaps not well documented. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Peter Hull
Member #1,136
March 2001
|
I did not know that. Is it also true for memory bitmaps? I was drawing into memory bitmaps and saving them from 2 threads, and it worked OK on macos.
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
On Windows, it works for memory bitmaps. I just tested it. I've also been running some informal tests with my ThreadPool. 8 jobs versus 1 is faster by a factor of between 2 and 3 times. This is some example code that uses my ThreadPool class that I've put together over the last few days. I will integrate it into Eagle soon, but this version is standalone (only depends on Allegro 5). API is super simple. 1#include "Pool.hpp"
2
3class Data {
4public :
5 int x;
6 Data() : x(0) {static int i = 1;x = i++;}
7};
8void* Factorialize(ALLEGRO_THREAD* t , void* data) {
9 Data* d = (Data*)data;
10 int z = d->x;
11 while (--z) {
12 d->x *= z;
13 }
14 return data;
15}
16int main(int argc , char** argv) {
17 if (!al_init()) {return -1;}
18
19 const int NDAT = 100;
20 Data* dat = new Data[NDAT];
21
22 ThreadPool tpool;
23 tpool.SetNumThreads(8);
24 for (int i = 0 ; i < NDAT ; ++i) {
25 tpool.AddJob(Factorialize , &dat[i]);
26 }
27
28 tpool.Start();
29 tpool.Finish();
30
31 for (int i = 0 ; i < NDAT ; ++i) {
32 Data* d = &dat[i];
33 printf("%d factorial is %d.\n" , i + 1 , d->x);
34 }
35
36 return 0;
37}
I'm not going to post it yet, for some reason I can't have more than exactly 853 jobs. If I add 854 jobs or more, the thread pool breaks and never finishes its work. UPDATE : My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|