static RwTaskletPluginInstanceHandle * rwlogd__component__instance_alloc(RwTaskletPluginComponent *self, RwTaskletPluginComponentHandle *h_component, struct rwtasklet_info_s * rwtasklet_info, RwTaskletPlugin_RWExecURL* instance_url) { rwlogd_component_ptr_t component; rwlogd_instance_ptr_t instance; RwTaskletPluginInstanceHandle *h_instance; gpointer handle; // Validate input parameters component = (rwlogd_component_ptr_t) h_component->priv; RW_CF_TYPE_VALIDATE(component, rwlogd_component_ptr_t); // Allocate a new rwlogd_instance structure instance = RW_CF_TYPE_MALLOC0(sizeof(*instance), rwlogd_instance_ptr_t); RW_CF_TYPE_VALIDATE(instance, rwlogd_instance_ptr_t); // Save the rwtasklet_info structure instance->rwtasklet_info = rwtasklet_info; // Allocate a gobject for the handle handle = g_object_new(RW_TASKLET_PLUGIN_TYPE_INSTANCE_HANDLE, 0); h_instance = RW_TASKLET_PLUGIN_INSTANCE_HANDLE(handle); h_instance->priv = (gpointer) instance; // Return the handle to the rwtasklet instance return h_instance; }
rwmsg_toytask_t * rwmsg_toytask_create(rwmsg_toysched_t *ts) { rwmsg_toysched_t *toysched = ts; rwsched_instance_ptr_t instance; rwmsg_toytask_t *toytask; static int toytask_id; // Get the rwsched instance from toysched instance = toysched->rwsched_instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Allocate memory for the new toytask toytask = RW_CF_TYPE_MALLOC0(sizeof(*toytask), rwtoytask_tasklet_ptr_t); RW_CF_TYPE_VALIDATE(toytask, rwtoytask_tasklet_ptr_t); toytask->rwsched_tasklet_info = rwsched_tasklet_new(instance); // Save the toysched instance struture within the toytask toytask->toysched = ts; // Get the next toytask id for this toytask toytask_id++; // Return the toytask pointer return toytask; }
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; }
rwdtsperf_component_ptr_t rwdtsperf_component_init(void) { rwdtsperf_component_ptr_t component; // Allocate a new rwdtsperf_component structure component = RW_CF_TYPE_MALLOC0(sizeof(*component), rwdtsperf_component_ptr_t); RW_CF_TYPE_VALIDATE(component, rwdtsperf_component_ptr_t); // Return the allocated component return component; }
uint64_t rwmsg_toyRtimer_add(rwmsg_toytask_t *toy, int ms, toytimer_cb_t cb, void *ud) { rwsched_instance_ptr_t instance; rwmsg_toytask_t *toytask = toy; struct rwmsg_toytimer_s *toytimer; //uint64_t nsec; // Validate input parameters RW_CF_TYPE_VALIDATE(toytask, rwtoytask_tasklet_ptr_t); // Get the rwsched instance from the toytask instance = toytask->toysched->rwsched_instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Allocate a toytimer container type and track it toytimer = RW_CF_TYPE_MALLOC0(sizeof(*toytimer), rwmsg_toytimer_ptr_t); RW_CF_TYPE_VALIDATE(toytimer, rwmsg_toytimer_ptr_t); // Create a CF runloop timer CFRunLoopTimerContext cf_context = { 0, NULL, NULL, NULL, NULL }; double timer_interval = ms * .001; rwsched_CFRunLoopRef runloop = rwsched_tasklet_CFRunLoopGetCurrent(toytask->rwsched_tasklet_info); rwsched_CFRunLoopTimerRef cftimer; // Create a CFRunLoopTimer as a runloop source for the toytimer cf_context.info = toytimer; cftimer = rwsched_tasklet_CFRunLoopTimerCreate(toytask->rwsched_tasklet_info, kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + timer_interval, timer_interval, 0, 0, rwmsg_toysched_Rtimer_callback, &cf_context); RW_CF_TYPE_VALIDATE(cftimer, rwsched_CFRunLoopTimerRef); rwsched_tasklet_CFRunLoopAddTimer(toytask->rwsched_tasklet_info, runloop, cftimer, instance->main_cfrunloop_mode); // Fill in the toytimer structure toytimer->id = cftimer->index; toytimer->cb = cb; toytimer->ud = ud; // Fill in the toytimer context structure toytimer->context.toytask = toy; toytimer->context.source.cftimer = cftimer; toytimer->context.u.toytimer.toytimer = toytimer; // Return the callback id return (uint64_t) toytimer->id; }
rwdtsperf_instance_ptr_t rwdtsperf_instance_alloc(rwdtsperf_component_ptr_t component, struct rwtasklet_info_s * rwtasklet_info, RwTaskletPlugin_RWExecURL *instance_url) { rwdtsperf_instance_ptr_t instance; // Validate input parameters RW_CF_TYPE_VALIDATE(component, rwdtsperf_component_ptr_t); RW_ASSERT(instance_url); // Allocate a new rwdtsperf_instance structure instance = RW_CF_TYPE_MALLOC0(sizeof(*instance), rwdtsperf_instance_ptr_t); RW_CF_TYPE_VALIDATE(instance, rwdtsperf_instance_ptr_t); // Save the rwtasklet_info structure instance->rwtasklet_info = rwtasklet_info; rwdtsperf_config_init(instance); // Return the allocated instance return instance; }
RwTaskletPluginComponentHandle * rwlogd__component__component_init(RwTaskletPluginComponent *self) { rwlogd_component_ptr_t component; RwTaskletPluginComponentHandle *h_component; gpointer handle; // Register the RW.Init types RW_CF_TYPE_REGISTER(rwlogd_component_ptr_t); RW_CF_TYPE_REGISTER(rwlogd_instance_ptr_t); // Allocate a new rwlogd_component structure component = RW_CF_TYPE_MALLOC0(sizeof(*component), rwlogd_component_ptr_t); RW_CF_TYPE_VALIDATE(component, rwlogd_component_ptr_t); // Allocate a gobject for the handle handle = g_object_new(RW_TASKLET_PLUGIN_TYPE_COMPONENT_HANDLE, 0); h_component = RW_TASKLET_PLUGIN_COMPONENT_HANDLE(handle); h_component->priv = (gpointer) component; // Return the handle to the rwtasklet component return h_component; }
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; }
uint64_t rwmsg_toyfd_add(rwmsg_toytask_t *toy, int fd, int pollbits, toyfd_cb_t cb, void *ud) { rwsched_instance_ptr_t instance; rwmsg_toytask_t *toytask = toy; //rwsched_dispatch_source_t source; struct rwmsg_toyfd_s *toyfd; // Validate input parameters RW_CF_TYPE_VALIDATE(toytask, rwtoytask_tasklet_ptr_t); // Get the rwsched instance from the toytask instance = toytask->toysched->rwsched_instance; RW_CF_TYPE_VALIDATE(instance, rwsched_instance_ptr_t); // Allocate a toyfd container type and track it toyfd = RW_CF_TYPE_MALLOC0(sizeof(*toyfd), rwmsg_toyfd_ptr_t); RW_CF_TYPE_VALIDATE(toyfd, rwmsg_toyfd_ptr_t); // Example of using CFSocket to manage file descriptors on a runloop using CFStreamCreatePairWithSocket() // http://lists.apple.com/archives/macnetworkprog/2003/Jul/msg00075.html CFSocketContext cf_context = { 0, NULL, NULL, NULL, NULL }; CFOptionFlags cf_callback_flags = 0; CFOptionFlags cf_option_flags = 0; rwsched_CFRunLoopRef runloop = rwsched_tasklet_CFRunLoopGetCurrent(toytask->rwsched_tasklet_info); rwsched_CFSocketRef cfsocket; rwsched_CFRunLoopSourceRef cfsource; // Use the pollbits to determine which socket callback events to register if (pollbits & POLLIN) { cf_callback_flags |= kCFSocketReadCallBack; cf_option_flags |= kCFSocketAutomaticallyReenableReadCallBack; } if (pollbits & POLLOUT) { cf_callback_flags |= kCFSocketWriteCallBack; cf_option_flags |= kCFSocketAutomaticallyReenableWriteCallBack; } // Create a CFSocket as a runloop source for the toyfd file descriptor cf_context.info = toyfd; cfsocket = rwsched_tasklet_CFSocketCreateWithNative(toytask->rwsched_tasklet_info, kCFAllocatorSystemDefault, fd, cf_callback_flags, rwmsg_toysched_io_callback, &cf_context); RW_CF_TYPE_VALIDATE(cfsocket, rwsched_CFSocketRef); rwsched_tasklet_CFSocketSetSocketFlags(toytask->rwsched_tasklet_info, cfsocket, cf_option_flags); cfsource = rwsched_tasklet_CFSocketCreateRunLoopSource(toytask->rwsched_tasklet_info, kCFAllocatorSystemDefault, cfsocket, 0); RW_CF_TYPE_VALIDATE(cfsource, rwsched_CFRunLoopSourceRef); rwsched_tasklet_CFRunLoopAddSource(toytask->rwsched_tasklet_info, runloop, cfsource, instance->main_cfrunloop_mode); // Fill in the toyfd structure toyfd->cf_ref = cfsocket; toyfd->id = cfsocket->index; toyfd->fd = fd; toyfd->cb = cb; toyfd->ud = ud; toyfd->toytask = toytask; // Fill in the read context structure if (pollbits & POLLIN) { toyfd->read_context.source.cfsource = cfsource; } // Fill in the write context structure if (pollbits & POLLOUT) { toyfd->write_context.source.cfsource = cfsource; } // Return the callback id return (uint64_t) toyfd->id; }