struct FixedBuf { FixedBuf (int sz) : pos(0), size(sz), buf((byte*)malloc(size)) {} ~FixedBuf () { free(buf); } int pos; int size; byte *buf; }; cairo_status_t writer (void *closure, const unsigned char *data, unsigned int length) { FixedBuf &buf = *(FixedBuf*)closure; if (buf.pos + (int)length >= buf.size) return CAIRO_STATUS_WRITE_ERROR; for (int i = 0; i < (int)length; ++i) buf.buf[buf.pos++] = (byte)data[i]; return CAIRO_STATUS_SUCCESS; } #define NLETTERS 10 double fontSize[NLETTERS][NLETTERS]; void initFontSizes () { for (int j = 0; j < NLETTERS; ++j) for (int i = 0; i < NLETTERS; ++i) fontSize[j][i] = floorf(10 * (20 + (10.0f * rand() / RAND_MAX)) / 10); } THREAD_RET THREAD_MOD runPure(void *param) { osMutexLock(&g_mutex); int id = (int)threadId++; osMutexUnlock(&g_mutex); char buf[1024]; const char* symbols[] = {"a", "b", "c", "d", "e", "f", "g", "h"}; int sz = 600; FixedBuf fb(16000); for (int i = 0; i < 20; ++i) { cairo_surface_t *surface; cairo_t *cr; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 400, 400); cr = cairo_create(surface); cairo_set_source_rgb(cr, 0, 0, 0); for (int j = 0; j < NLETTERS; ++j) { for (int i = 0; i < NLETTERS; ++i) { cairo_move_to(cr, (i+1) * sz / (NLETTERS + 1), (j+1) * sz / (NLETTERS + 1)); cairo_select_font_face(cr, "Arial", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, fontSize[j][i]); cairo_show_text(cr, symbols[(i + j) % NELEM(symbols)]); } } cairo_surface_write_to_png_stream(surface, writer, &fb); int len = fb.pos; int h = hash(fb.buf, len); printf("%i: %i\n", id, len); sprintf(buf, "png/%i_%lu.png", len, h); osMutexLock(&g_mutex); if (!g_map.find(buf)) { g_map.insert(buf, 1); FileOutput fo(buf); fo.write(fb.buf, len); fo.flush(); } osMutexUnlock(&g_mutex); fb.pos = 0; } return 0; } #define NUM 4 void TestConcurrent () { initFontSizes(); osMutexCreate(&g_mutex); for (int i = 0; i < NUM; ++i) { osThreadCreate(runPure, NULL); } }