static void
		start_node(void *context)
{
	dispatch_group_t g = (dispatch_group_t)(context);
	size_t i;
	dispatch_queue_t this_q = dispatch_get_current_queue();

	for (i = 0; i < COUNT; i++) {
		dispatch_group_async_f(g, this_q, NULL, work);
	}

	dispatch_group_async_f(g, this_q, NULL, node_done);

	//MU_MESSAGE("Spawned node %s", dispatch_queue_get_label(dispatch_get_current_queue()));
}
Esempio n. 2
0
void load_image(ConvertContext *context) {
    int result = RESULT_OK;
    char *error_desc;
    ExceptionType error_type;

	// wait for resources to be available
	dispatch_semaphore_wait(context->conv_semaphore, DISPATCH_TIME_FOREVER);
	
	// load image
	if (MagickReadImage(context->mw, context->src_path) == MagickFalse) {
		// deal with error
        error_desc = MagickGetException(context->mw, &error_type);
        asprintf(&context->results.message,"Error loading image (%s): %s\n",error_desc,context->src_path);
        error_desc = (char *)MagickRelinquishMemory(error_desc);
        result += RESULT_ERROR;
    }
    if (result == RESULT_OK) {
        // get image info
        context->hasAlphaChannel = MagickGetImageAlphaChannel(context->mw);
        if  (context->hasAlphaChannel == MagickTrue) {
            context->imageWidth = MagickGetImageWidth(context->mw);
            context->imageHeight = MagickGetImageHeight(context->mw);

            // get pixel data
            context->pixel_count = context->imageWidth * context->imageHeight;
            context->pixels = malloc(context->pixel_count * sizeof(PixelData));
            if (context->pixels == NULL) {
                asprintf(&context->results.message, "Error allocating memory for pixel data: %s\n",context->src_path);
                result += RESULT_ERROR;
            } else {
                if (MagickExportImagePixels(context->mw, 0, 0, context->imageWidth, context->imageHeight, "ARGB", CharPixel, context->pixels) == MagickFalse) {
                    error_desc = MagickGetException(context->mw, &error_type);
                    asprintf(&context->results.message, "Error exporting pixel data (%s): %s\n",error_desc,context->src_path);
                    error_desc = (char *)MagickRelinquishMemory(error_desc);
                    result += RESULT_ERROR;
                }
            }
        }
    }
    if (result != RESULT_OK) {
        // clean up mess
		context->results.result = result;
		dispatch_group_async_f(context->conv_group, dispatch_get_main_queue(), context, (void (*)(void *))finish_image);
    } else {
		// move to next step
		dispatch_group_async_f(context->conv_group, context->conv_queue, context, (void (*)(void *))conv_image);
	}
}
static void do_test(void)
{
	size_t i;
	char buf[1000];
	dispatch_group_t g = dispatch_group_create();

	for (i = 0; i < QUEUES; i++) {
#ifdef WIN32
		_snprintf(buf, sizeof(buf), "com.example.memoryload-node#%ld", i);
#else
		snprintf(buf, sizeof(buf), "com.example.memoryload-node#%ld", (long int)i);
#endif
		queues[i] = dispatch_queue_create(buf, NULL);
		dispatch_suspend(queues[i]);
	}

	for (i = 0; i < QUEUES; i++) {
		dispatch_group_async_f(g, queues[i], g, start_node);
	}

	dispatch_group_notify_f(g, dispatch_get_main_queue(), NULL, collect);

	for (i = 0; i < QUEUES; i++) {
		dispatch_resume(queues[i]);
		dispatch_release(queues[i]);
	}
}
Esempio n. 4
0
void group::async(
    operation *r,
    const queue &q
)
{
    dispatch_queue_t nat_q = (dispatch_queue_t)q.native();

    XDISPATCH_ASSERT( nat_q );
    dispatch_group_async_f( m_native, nat_q, r, _xdispatch_run_operation );
}
Esempio n. 5
0
void ISPCLaunch(void *func, void *data) {
    if (!initialized) {
        fprintf(stderr, "You must call TasksInit() before launching tasks.\n");
        exit(1);
    }
    TaskInfo *ti = new TaskInfo;
    ti->func = func;
    ti->data = data;
    dispatch_group_async_f(gcdGroup, gcdQueue, ti, lRunTask);
}
Esempio n. 6
0
void save_image(ConvertContext *context) {
    int result = RESULT_OK;
    char *error_desc;
    ExceptionType error_type;
	
    // get pixel data
    if (context->hasAlphaChannel == MagickTrue) {
        if (MagickImportImagePixels(context->mw, 0, 0, context->imageWidth, context->imageHeight, "ARGB", CharPixel, context->pixels)  == MagickFalse) {
            error_desc = MagickGetException(context->mw, &error_type);
            asprintf(&context->results.message, "Error exporting pixel data (%s): %s\n",error_desc,context->src_path);
            error_desc = (char *)MagickRelinquishMemory(error_desc);
            result += RESULT_ERROR;
        }
    }
    
    // convert image to PNG
    if (result == RESULT_OK) {
        if (MagickSetImageFormat(context->mw,"PNG") == MagickFalse) {
            error_desc = MagickGetException(context->mw, &error_type);
			asprintf(&context->results.message,"Error converting image (%s): %s\n",error_desc,context->src_path);
            error_desc = (char *)MagickRelinquishMemory(error_desc);
            result += RESULT_ERROR;
        }
    }
	
	// activate/deactivate alpha channel
	MagickSetImageAlphaChannel(context->mw, (context->results.alpha_type == ALPHA_TYPE_NONE ? DeactivateAlphaChannel : ActivateAlphaChannel));

    // make sure image is saved as RGB and not crunched down to grayscale
	MagickSetType(context->mw, (context->results.alpha_type == ALPHA_TYPE_NONE ? TrueColorType : TrueColorMatteType));
	
	// save image to disk
    if (result == RESULT_OK) {
        if (MagickWriteImage(context->mw, context->dst_path) == MagickFalse) {
            error_desc = MagickGetException(context->mw, &error_type);
            asprintf(&context->results.message, "Error saving image (%s): %s\n",error_desc,context->dst_path);
            error_desc = (char *)MagickRelinquishMemory(error_desc);
            result += RESULT_ERROR;
        }
    }
	
	if (result == RESULT_OK && context->options.delete_original != 0) {
		if (unlink(context->src_path) == -1) {
			asprintf(&context->results.message, "Unable to delete original image (%s): %s\n", strerror(errno), context->src_path);
			result += RESULT_ERROR;
		}
    }
    
	// cleanup and report results
	context->results.result = result;
	dispatch_group_async_f(context->conv_group, dispatch_get_main_queue(), context, (void (*)(void *))finish_image);
}
Esempio n. 7
0
void dispatch_group_function() {
	long res;
	dispatch_group_t group;

	MU_BEGIN_TEST(dispatch_group_function);

	group = create_group(100, 0);
	MU_ASSERT_NOT_NULL(group);

	dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
	
	// should be OK to re-use a group
	dispatch_group_async_f(group, dispatch_get_global_queue(0, 0), 0, foo);
	dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

	dispatch_release(group);
	group = NULL;
	
	group = create_group(3, 7);
	MU_ASSERT_NOT_NULL(group);

	res = dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5ull * NSEC_PER_SEC));
    MU_ASSERT_EQUAL(!res, 0);

	// retry after timeout (this time succeed)
	res = dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5ull * NSEC_PER_SEC));
    MU_ASSERT_EQUAL(res, 0);

	dispatch_release(group);
	group = NULL;

	group = create_group(100, 0);
	MU_ASSERT_NOT_NULL(group);

	dispatch_group_notify_f(group, dispatch_get_main_queue(), 0, group_notify);
	
	dispatch_release(group);
	group = NULL;

	dispatch_main();

	MU_FAIL("Should never reach this");
	MU_END_TEST
}
Esempio n. 8
0
static VALUE
rb_queue_dispatch_async(VALUE self, SEL sel, int argc, VALUE *argv)
{
    rb_vm_block_t *block = get_prepared_block();
    VALUE group;
    rb_scan_args(argc, argv, "01", &group);

    if (group != Qnil) {
	Check_Group(group);
	dispatch_group_async_f(RGroup(group)->group, RQueue(self)->queue,
		(void *)block, rb_block_dispatcher);
    }
    else {
	dispatch_async_f(RQueue(self)->queue, (void *)block,
		rb_block_dispatcher);
    }

    return Qnil;
}
Esempio n. 9
0
static dispatch_group_t create_group(size_t count, int delay) {
	size_t i;
	int* param;

	dispatch_group_t group = dispatch_group_create();

	for (i = 0; i < count; ++i) {
		dispatch_queue_t queue = dispatch_queue_create("foo", NULL);
		param = (int*)malloc(sizeof(int));
		*param = delay;

		MU_ASSERT_NOT_NULL(queue);
		MU_ASSERT_NOT_NULL(param);

		dispatch_group_async_f(group, queue, param, work);

		dispatch_release(queue);
	}
	return group;
}
Esempio n. 10
0
void EnqueueTasks(const vector<Task *> &tasks) {
    if (PbrtOptions.nCores == 1) {
        for (unsigned int i = 0; i < tasks.size(); ++i)
            tasks[i]->Run();
        return;
    }
#ifdef PBRT_USE_GRAND_CENTRAL_DISPATCH
    for (uint32_t i = 0; i < tasks.size(); ++i)
        dispatch_group_async_f(gcdGroup, gcdQueue, tasks[i], lRunTask);
#else
    if (!threads)
        TasksInit();

    {   MutexLock lock(*taskQueueMutex);
        for (unsigned int i = 0; i < tasks.size(); ++i)
            taskQueue.push_back(tasks[i]);
    }
    tasksRunningCondition.Lock();
    numUnfinishedTasks += tasks.size();
    tasksRunningCondition.Unlock();

    workerSemaphore.Post(tasks.size());
#endif
}
Esempio n. 11
0
void EnqueueTasks(const vector<Task *> &tasks) {
#ifdef PBRT_USE_GRAND_CENTRAL_DISPATCH
    static bool oneThread = (getenv("PBRT_NTHREADS") &&
                               atoi(getenv("PBRT_NTHREADS")) == 1);
    for (u_int i = 0; i < tasks.size(); ++i)
        if (oneThread)
            dispatch_sync_f(gcdQueue, tasks[i], lRunTask);
        else
            dispatch_group_async_f(gcdGroup, gcdQueue, tasks[i], lRunTask);
#else
    if (!threads)
        TasksInit();

    { MutexLock lock(*taskQueueMutex);
    for (unsigned int i = 0; i < tasks.size(); ++i)
        taskQueue.push_back(tasks[i]);
    }
    tasksRunningCondition.Lock();
    numUnfinishedTasks += tasks.size();
    tasksRunningCondition.Unlock();

    workerSemaphore.Post(tasks.size());
#endif
}
Esempio n. 12
0
void asyncDispatch(dispatch_group_t g, void *args, dispatch_function_t func) {
    return dispatch_group_async_f(g, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), args, func);
}
Esempio n. 13
0
void process_image(ConvertContext *context) {
	context->results.result = RESULT_OK;
	context->mw = NewMagickWand();
	dispatch_group_async_f(context->conv_group, context->load_queue, context, (void (*)(void *))load_image);
}
Esempio n. 14
0
void conv_image(ConvertContext *context) {
    int result = RESULT_OK;
    BackgroundMetric *backgrounds = NULL;
    int bkgnd_size = BKGND_GROWTH;
    int bkgnd_count;
    int bkgnd_index;
    int bkgnd_selected = BKGND_NONE;
    double bkgnd_ratio = 0.0;
    unsigned long bkgnd_pixels;
    
    unsigned long pixel_index;
    int red;
    int grn;
    int blu;
    int alp;
    int inv;
    int bkgnd_red;
    int bkgnd_grn;
    int bkgnd_blu;
    int alpha_other = 0;
    int alpha_match = 0;
    int alpha_marginal = 0;
    int alpha_type = context->options.manual_alpha;	// defaults to ALPHA_TYPE_UNKNOWN

    // check alpha
    if (result == RESULT_OK && context->hasAlphaChannel == MagickTrue &&
		(alpha_type == ALPHA_TYPE_UNKNOWN || alpha_type == ALPHA_TYPE_ASSOCIATED)) {

        // allocate buffer for background metrics
        backgrounds = malloc(sizeof(BackgroundMetric) * bkgnd_size);
        if (backgrounds == NULL) {
            asprintf(&context->results.message, "Error allocating memory for background metrics");
			result += RESULT_ERROR;
        }
        
        // load starting background metrics
		if (result == RESULT_OK) {
			backgrounds[BKGND_BLACK].red = 0;
			backgrounds[BKGND_BLACK].grn = 0;
			backgrounds[BKGND_BLACK].blu = 0;
			backgrounds[BKGND_BLACK].count = 0;        
			backgrounds[BKGND_WHITE].red = 255;
			backgrounds[BKGND_WHITE].grn = 255;
			backgrounds[BKGND_WHITE].blu = 255;
			backgrounds[BKGND_WHITE].count = 0;        
			bkgnd_count = 2;
		}
        
        // analyze image
        
        // get background color
        if (result == RESULT_OK) {
            bkgnd_pixels = 0;
            pixel_index = 0;
            while (result == RESULT_OK && pixel_index < context->pixel_count) {
                red = context->pixels[pixel_index].red;
                grn = context->pixels[pixel_index].grn;
                blu = context->pixels[pixel_index].blu;
                alp = context->pixels[pixel_index].alp;
                // transparent pixels only...
                if (alp == 0) {
                    bkgnd_pixels++;
                    // look for color in metrics
                    for (bkgnd_index = 0; bkgnd_index < bkgnd_count; bkgnd_index++) {
                        if (red == backgrounds[bkgnd_index].red && grn == backgrounds[bkgnd_index].grn && blu == backgrounds[bkgnd_index].blu) {
                            backgrounds[bkgnd_index].count++;
                            break;
                        }
                    }
                    if (bkgnd_index == bkgnd_count) {
                        // add another metric
                        if (bkgnd_count == bkgnd_size) {
                            bkgnd_size += BKGND_GROWTH;
                            backgrounds = realloc(backgrounds, sizeof(BackgroundMetric) * bkgnd_size);
                            if (backgrounds == NULL) {
                                asprintf(&context->results.message,"Error allocating memory for background metrics");
                                result += RESULT_ERROR;
                                break;
                            }
                        }
                    backgrounds[bkgnd_index].red = red;
                    backgrounds[bkgnd_index].grn = grn;
                    backgrounds[bkgnd_index].blu = blu;
                    backgrounds[bkgnd_index].count = 1;
                    bkgnd_count++;
                    }
                }
                pixel_index++;
            }
        }
        
        // find background color in metrics
        if (result == RESULT_OK) {
            for (bkgnd_index = 0; bkgnd_index < bkgnd_count; bkgnd_index++) {
                if (backgrounds[bkgnd_index].count > (bkgnd_selected == BKGND_NONE ? 0 : backgrounds[bkgnd_selected].count))
                    bkgnd_selected = bkgnd_index;
            }
            // make sure the selected color wins by a good margin
            if (bkgnd_selected != BKGND_NONE) {
                
                bkgnd_ratio = (double)backgrounds[bkgnd_selected].count / (double)bkgnd_pixels;
                if (bkgnd_ratio < context->options.bkgnd_ratio && !context->options.force) {
                    asprintf(&context->results.message, "Inconsistent background color (ratio at %g; should be %g or greater): %s\n",bkgnd_ratio, context->options.bkgnd_ratio, context->src_path);
                    result += RESULT_WARNING;
                }
            }
        }
        
        if (result == RESULT_OK && bkgnd_selected != BKGND_NONE) {
            // check translucent pixels
            pixel_index = 0;
            while (pixel_index < context->pixel_count) {
                alp = context->pixels[pixel_index].alp;

                if (alp > 0 && alp < 255) {
                    red = context->pixels[pixel_index].red;
                    grn = context->pixels[pixel_index].grn;
                    blu = context->pixels[pixel_index].blu;
                    inv = 255 - alp;

                    red = red - (int)roundf((float)(inv * backgrounds[bkgnd_selected].red)/255.0);
                    grn = grn - (int)roundf((float)(inv * backgrounds[bkgnd_selected].grn)/255.0);
                    blu = blu - (int)roundf((float)(inv * backgrounds[bkgnd_selected].blu)/255.0);

                    // check range of pixel
                    if (red <= alp && red >= 0 &&
                        blu <= alp && blu >= 0 &&
                        grn <= alp && grn >= 0) {
                        alpha_match++;
					} else if (red <= alp + 1 && red >= -1 &&
							   blu <= alp + 1 && blu >= -1 &&
							   grn <= alp + 1 && grn >= -1) {
						alpha_marginal++;
                    } else {
                        alpha_other++;
                    }
                }
                pixel_index++;
            }

			// when associated alpha is specified, adjust pixel counts to make it happen
			if (alpha_type == ALPHA_TYPE_ASSOCIATED) {
				alpha_match = (alpha_match > 0 ? alpha_match : 1);
				alpha_marginal += alpha_other;
				alpha_other = 0;
			}

            // If all the translucent pixels fall within the proper range, then
            // this the alpha is likely pre-multiplied (associated) over background
            if (alpha_match > 0 && alpha_other == 0) {
                alpha_type = ALPHA_TYPE_ASSOCIATED;
                if (bkgnd_selected != BKGND_BLACK && bkgnd_selected != BKGND_WHITE) {
                    if (!context->options.force) {
                        asprintf(&context->results.message,
								 "Invalid background - must be black or white (R:%hhu G:%hhu B:%hhu): %s\n",
                                 backgrounds[bkgnd_selected].red,
                                 backgrounds[bkgnd_selected].grn,
                                 backgrounds[bkgnd_selected].blu,
                                 context->src_path);
                        result += RESULT_WARNING;
                    }
                }
            } else {
                // straight (unassociated) alpha
                alpha_type = ALPHA_TYPE_UNASSOCIATED;
            }
        }

        if (result == RESULT_OK && (alpha_type == ALPHA_TYPE_ASSOCIATED)) {
            // correct image
            pixel_index = 0;
            while (result == RESULT_OK && pixel_index < context->pixel_count) {
                red = context->pixels[pixel_index].red;
                grn = context->pixels[pixel_index].grn;
                blu = context->pixels[pixel_index].blu;
                alp = context->pixels[pixel_index].alp;
                inv = 255 - alp;

                if (alp > 0 && alp < 255) {
                    /*

                     Standard image composition formula
                     (foreground through a mask over a background)

                     Comp = (Fg * A) + ((1 - A) * Bg)

                     So here is how we would get the foreground back...

                     Fg = (Comp - ((1 - A) * Bg)) / A

                     */
                    if (bkgnd_selected == BKGND_BLACK) {
                        // this one is easy...
                        // Fg = Comp / A
                        if (alpha_marginal != 0) {
                            red = (red > alp ? alp : red);
                            grn = (grn > alp ? alp : grn);
                            blu = (blu > alp ? alp : blu);
                        }
                        if (red != 0)
                            red = (int)roundf((float)(red * 255) / (float)alp);
                        if (grn != 0)
                            grn = (int)roundf((float)(grn * 255) / (float)alp);
                        if (blu != 0)
                            blu = (int)roundf((float)(blu * 255) / (float)alp);
                    } else if (bkgnd_selected == BKGND_WHITE) {
                        // much harder...
                        // Fg = (Comp - (1 - A)) / A
                        if (alpha_marginal != 0) {
                            red = (red < inv ? inv : red);
                            grn = (grn < inv ? inv : grn);
                            blu = (blu < inv ? inv : blu);
                        }
                        if (red != 255)
                            red = (int)roundf((float)((red - inv) * 255) / (float)alp);
                        if (grn != 255)
                            grn = (int)roundf((float)((grn - inv) * 255) / (float)alp);
                        if (blu != 255)
                            blu = (int)roundf((float)((blu - inv) * 255) / (float)alp);
                    } else {
                        // way harder!  (not sure if this really works)
                        // Fg = (Comp - ((1 - A) * Bg)) / A
                        bkgnd_red = (int)roundf((float)(inv * backgrounds[bkgnd_selected].red)/255.0);
                        bkgnd_grn = (int)roundf((float)(inv * backgrounds[bkgnd_selected].grn)/255.0);
                        bkgnd_blu = (int)roundf((float)(inv * backgrounds[bkgnd_selected].blu)/255.0);
                        if (alpha_marginal != 0) {
                            red = (red < bkgnd_red ? bkgnd_red : red);
                            grn = (grn < bkgnd_grn ? bkgnd_grn : grn);
                            blu = (blu < bkgnd_blu ? bkgnd_blu : blu);
                        }
                        red = (int)roundf((float)((red - bkgnd_red) * 255) / (float)alp);
                        grn = (int)roundf((float)((grn - bkgnd_grn) * 255) / (float)alp);
                        blu = (int)roundf((float)((blu - bkgnd_blu) * 255) / (float)alp);
                    }
                    context->pixels[pixel_index].red = red;
                    context->pixels[pixel_index].blu = blu;
                    context->pixels[pixel_index].grn = grn;
                }
                pixel_index++;
            }
        }
    }

	if (alpha_type == ALPHA_TYPE_UNKNOWN || context->hasAlphaChannel == MagickFalse)
		alpha_type = ALPHA_TYPE_NONE;

	// fill in results
	context->results.alpha_type  = alpha_type;
	context->results.bkgnd_type  = (bkgnd_selected == BKGND_NONE || bkgnd_selected == BKGND_BLACK || bkgnd_selected == BKGND_WHITE ? bkgnd_selected : BKGND_OTHER);
	context->results.bkgnd_ratio = bkgnd_ratio;
	context->results.bkgnd_red   = (bkgnd_selected == BKGND_NONE ? 0 : backgrounds[bkgnd_selected].red);
	context->results.bkgnd_grn   = (bkgnd_selected == BKGND_NONE ? 0 : backgrounds[bkgnd_selected].grn);
	context->results.bkgnd_blu   = (bkgnd_selected == BKGND_NONE ? 0 : backgrounds[bkgnd_selected].blu);

    if (backgrounds != NULL) {
        free(backgrounds);
    }
    
	if (result != RESULT_OK || context->options.dry_run != 0) {
		// clean up mess
		context->results.result = result;
		dispatch_group_async_f(context->conv_group, dispatch_get_main_queue(), context, (void (*)(void *))finish_image);
    } else {
		// move to next step
		dispatch_group_async_f(context->conv_group, context->save_queue, context, (void (*)(void *))save_image);
	}
}