rwsched_tasklet_t * rwsched_tasklet_new(rwsched_instance_t *instance) { rwsched_tasklet_ptr_t sched_tasklet; //int i; // Validate input paraemters RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Allocate memory for the new sched_tasklet sched_tasklet structure and track it sched_tasklet = RW_CF_TYPE_MALLOC0(sizeof(*sched_tasklet), rwsched_tasklet_ptr_t); RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ref(instance); sched_tasklet->instance = instance; sched_tasklet->rwresource_track_handle = RW_RESOURCE_TRACK_CREATE_CONTEXT("Tasklet Context"); // Look for an unused entry in tasklet_array (start the indexes at 1 for now) int i; for (i = 1 ; i < instance->tasklet_array->len ; i++) { if (g_array_index(instance->tasklet_array, rwsched_tasklet_ptr_t, i) == NULL) { g_array_index(instance->tasklet_array, rwsched_tasklet_ptr_t, i) = sched_tasklet; break; } } if (i >= instance->tasklet_array->len) { // Insert a new element at the end of the array g_array_append_val(instance->tasklet_array, sched_tasklet); } #ifdef _CF_ // Allocate an array of cftimer pointers and track it rwsched_CFRunLoopTimerRef cftimer = NULL; sched_tasklet->cftimer_array = g_array_sized_new(TRUE, TRUE, sizeof(void *), 256); g_array_append_val(sched_tasklet->cftimer_array, cftimer); // Allocate an array of cfsocket pointers and track it rwsched_CFSocketRef cfsocket = NULL; sched_tasklet->cfsocket_array = g_array_sized_new(TRUE, TRUE, sizeof(void *), 256); g_array_append_val(sched_tasklet->cfsocket_array, cfsocket); // Allocate an array of cfsocket pointers and track it rwsched_CFRunLoopSourceRef cfsource = NULL; sched_tasklet->cfsource_array = g_array_sized_new(TRUE, TRUE, sizeof(void *), 256); g_array_append_val(sched_tasklet->cfsource_array, cfsource); // Allocate an array of dispatch_what pointers and track it rwsched_dispatch_what_ptr_t dispatch_what = NULL; sched_tasklet->dispatch_what_array = g_array_sized_new(TRUE, TRUE, sizeof(void *), 256); g_array_append_val(sched_tasklet->dispatch_what_array, dispatch_what); #endif rwsched_tasklet_ref(sched_tasklet); ck_pr_inc_32(&g_rwsched_tasklet_count); // Return the allocated sched_tasklet sched_tasklet structure return sched_tasklet; }
CF_EXPORT rwsched_CFRunLoopTimerRef rwsched_tasklet_CFRunLoopTimerCreate(rwsched_tasklet_ptr_t sched_tasklet, CFAllocatorRef allocator, CFAbsoluteTime fireDate, CFTimeInterval interval, CFOptionFlags flags, CFIndex order, rwsched_CFRunLoopTimerCallBack callout, rwsched_CFRunLoopTimerContext *context) { // Validate input parameters RW_CF_TYPE_VALIDATE(sched_tasklet, rwsched_tasklet_ptr_t); rwsched_instance_ptr_t instance = sched_tasklet->instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); rwsched_CFRunLoopTimerRef rwsched_timer; unsigned int i; RW_ASSERT(context->info); // Allocate a rwsched container type and track it rwsched_timer = RW_CF_TYPE_MALLOC0(sizeof(*rwsched_timer), rwsched_CFRunLoopTimerRef); // Look for an unused entry in cftimer_array (start the indexes at 1 for now) //RW_GOBJECT_TYPE_VALIDATE(sched_tasklet->cftimer_array, GArray); for (i = 1 ; i < sched_tasklet->cftimer_array->len ; i++) { if (g_array_index(sched_tasklet->cftimer_array, rwsched_CFRunLoopTimerRef, i) == NULL) { g_array_index(sched_tasklet->cftimer_array, rwsched_CFRunLoopTimerRef, i) = rwsched_timer; break; } } if (i >= sched_tasklet->cftimer_array->len) { // Insert a new element at the end of the array g_array_append_val(sched_tasklet->cftimer_array, rwsched_timer); } // Mark the rwsched_timer as in use RW_CF_TYPE_VALIDATE(rwsched_timer, rwsched_CFRunLoopTimerRef); rwsched_timer->index = i; if (interval == 0) { rwsched_timer->onetime_timer = 1; rwsched_timer->ott.allocator = allocator; rwsched_timer->ott.flags = flags; rwsched_timer->ott.order = order; } // Call the native CFRunLoop function if (context && context->info == NULL) { context->info = rwsched_timer; } rwsched_timer->tmp_context = *context; rwsched_timer->tmp_context.info = rwsched_timer; rwsched_timer->cf_callout = callout; rwsched_tasklet_ref(sched_tasklet); rwsched_timer->callback_context.tasklet_info = sched_tasklet; rwsched_instance_ref(instance); rwsched_timer->callback_context.instance = instance; rwsched_timer->cf_object = CFRunLoopTimerCreate(allocator, fireDate, interval, flags, order, rwsched_cftimer_callout_intercept, &rwsched_timer->tmp_context); rwsched_timer->cf_context = *context; // Return the rwsched container type return rwsched_timer; }
rwsched_instance_t * rwsched_instance_new(void) { struct rwsched_instance_s *instance; // Allocate memory for the new instance // Register the rwsched instance types RW_CF_TYPE_REGISTER(rwsched_instance_ptr_t); RW_CF_TYPE_REGISTER(rwsched_tasklet_ptr_t); rwsched_CFRunLoopInit(); rwsched_CFSocketInit(); // Allocate the Master Resource-Tracking Handle g_rwresource_track_handle = RW_RESOURCE_TRACK_CREATE_CONTEXT("The Master Context"); // Allocate a rwsched instance type and track it instance = RW_CF_TYPE_MALLOC0(sizeof(*instance), rwsched_instance_ptr_t); RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Set the instance configuration instance->config.single_thread = TRUE; // For now use libdispatch only instance->use_libdispatch_only = TRUE; // libdispatch_init(); // Fake up a rwqueue placeholder object to use as the (NULL) DISPATCH_TARGET_QUEUE_DEFAULT RW_ASSERT(instance->use_libdispatch_only); instance->default_rwqueue = (rwsched_dispatch_queue_t) RW_MALLOC0_TYPE(sizeof(*instance->default_rwqueue), rwsched_dispatch_queue_t); RW_ASSERT_TYPE(instance->default_rwqueue, rwsched_dispatch_queue_t); instance->default_rwqueue->header.libdispatch_object._dq = DISPATCH_TARGET_QUEUE_DEFAULT; // Fake up a rwqueue placeholder object to use as DISPATCH_TARGET_QUEUE_MAIN RW_ASSERT(instance->use_libdispatch_only); instance->main_rwqueue = (rwsched_dispatch_queue_t) RW_MALLOC0_TYPE(sizeof(*instance->main_rwqueue), rwsched_dispatch_queue_t); RW_ASSERT_TYPE(instance->main_rwqueue, rwsched_dispatch_queue_t); instance->main_rwqueue->header.libdispatch_object._dq = dispatch_get_main_queue(); // Fake up rwqueue placeholder objects for the usual four global // queues. The pri values are not 0,1,2,3 or similar, they are // -MAX, -2, 0, 2. We do not support arbitrary pri values, although // I think the dispatch API is intended to. RW_ASSERT(instance->use_libdispatch_only); RW_STATIC_ASSERT(RWSCHED_DISPATCH_QUEUE_GLOBAL_CT == 4); static long pris[RWSCHED_DISPATCH_QUEUE_GLOBAL_CT] = { DISPATCH_QUEUE_PRIORITY_HIGH, DISPATCH_QUEUE_PRIORITY_DEFAULT, DISPATCH_QUEUE_PRIORITY_LOW, DISPATCH_QUEUE_PRIORITY_BACKGROUND }; int i; for (i=0; i<RWSCHED_DISPATCH_QUEUE_GLOBAL_CT; i++) { instance->global_rwqueue[i].pri = pris[i]; instance->global_rwqueue[i].rwq = (rwsched_dispatch_queue_t) RW_MALLOC0_TYPE(sizeof(*instance->global_rwqueue[i].rwq), rwsched_dispatch_queue_t); RW_ASSERT_TYPE(instance->global_rwqueue[i].rwq, rwsched_dispatch_queue_t); instance->global_rwqueue[i].rwq->header.libdispatch_object._dq = dispatch_get_global_queue(pris[i], 0); RW_ASSERT(instance->global_rwqueue[i].rwq->header.libdispatch_object._dq); } instance->main_cfrunloop_mode = kCFRunLoopDefaultMode; //instance->main_cfrunloop_mode = CFSTR("TimerMode"); //instance->deferred_cfrunloop_mode = CFSTR("Deferred Mode"); // Allocate an array of tasklet pointers and track it rwsched_tasklet_t *tasklet = NULL; instance->tasklet_array = g_array_sized_new(TRUE, TRUE, sizeof(void *), 256); g_array_append_val(instance->tasklet_array, tasklet); rwsched_instance_ref(instance); ck_pr_inc_32(&g_rwsched_instance_count); //RW_ASSERT(g_rwsched_instance_count <= 2); g_rwsched_instance = instance; instance->rwlog_instance = rwlog_init("RW.Sched"); // Return the instance pointer return instance; }