void timer_handler(void* context) { struct timeval now_tv; double now; double goal; double jitter; double drift; gettimeofday(&now_tv, NULL); now = now_tv.tv_sec + ((double)now_tv.tv_usec / (double)USEC_PER_SEC); if (first == 0) { first = now; } goal = first + interval_d * count; jitter = goal - now; drift = jitter - last_jitter; count += dispatch_source_get_data(timer); jittersum += jitter; driftsum += drift; printf("%4d: jitter %f, drift %f\n", count, jitter, drift); if (count >= target) { test_double_less_than("average jitter", fabs(jittersum) / (double)count, 0.0001); test_double_less_than("average drift", fabs(driftsum) / (double)count, 0.0001); test_stop(); } last_jitter = jitter; }
int main(void) { const char *path = "/usr/share/dict/words"; struct stat sb; dispatch_test_start("Dispatch Source Read"); int infd = open(path, O_RDONLY); if (infd == -1) { perror(path); exit(EXIT_FAILURE); } if (fstat(infd, &sb) == -1) { perror(path); exit(EXIT_FAILURE); } bytes_total = sb.st_size; if (fcntl(infd, F_SETFL, O_NONBLOCK) != 0) { perror(path); exit(EXIT_FAILURE); } if (!dispatch_test_check_evfilt_read_for_fd(infd)) { test_skip("EVFILT_READ kevent not firing for test file"); test_fin(NULL); } dispatch_queue_t main_q = dispatch_get_main_queue(); test_ptr_notnull("dispatch_get_main_queue", main_q); dispatch_source_t reader = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, infd, 0, main_q); test_ptr_notnull("dispatch_source_create", reader); assert(reader); dispatch_source_set_event_handler(reader, ^{ size_t estimated = dispatch_source_get_data(reader); fprintf(stderr, "bytes available: %zu\n", estimated); test_double_less_than_or_equal("estimated", estimated, bytes_total - bytes_read); const ssize_t bufsiz = 1024*500; // 500 KB buffer static char buffer[1024*500]; // 500 KB buffer ssize_t actual = read(infd, buffer, sizeof(buffer)); bytes_read += actual; printf("bytes read: %zd\n", actual); if (actual < bufsiz) { actual = read(infd, buffer, sizeof(buffer)); bytes_read += actual; // confirm EOF condition test_long("EOF", actual, 0); dispatch_source_cancel(reader); } });
void test_proc(pid_t bad_pid) { dispatch_source_t proc_s[PID_CNT], proc; int res; pid_t pid, monitor_pid; event_cnt = 0; // Creates a process and register multiple observers. Send a signal, // exit the process, etc., and verify all observers were notified. posix_spawnattr_t attr; res = posix_spawnattr_init(&attr); assert(res == 0); #if HAVE_DECL_POSIX_SPAWN_START_SUSPENDED res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED); assert(res == 0); #endif char* args[] = { "/bin/sleep", "2", NULL }; res = posix_spawnp(&pid, args[0], NULL, &attr, args, NULL); if (res < 0) { perror(args[0]); exit(127); } res = posix_spawnattr_destroy(&attr); assert(res == 0); dispatch_group_t group = dispatch_group_create(); assert(pid > 0); monitor_pid = bad_pid ? bad_pid : pid; // rdar://problem/8090801 int i; for (i = 0; i < PID_CNT; ++i) { dispatch_group_enter(group); proc = proc_s[i] = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, monitor_pid, DISPATCH_PROC_EXIT, dispatch_get_global_queue(0, 0)); test_ptr_notnull("dispatch_source_proc_create", proc); dispatch_source_set_event_handler(proc, ^{ long flags = dispatch_source_get_data(proc); test_long("DISPATCH_PROC_EXIT", flags, DISPATCH_PROC_EXIT); event_cnt++; dispatch_source_cancel(proc); }); dispatch_source_set_cancel_handler(proc, ^{ dispatch_group_leave(group); });
static void onSocketAccept() { if( ! listener ) return; SocketClientRef client = calloc(1, sizeof(SocketClient)); assert(client); socklen_t len = sizeof(client->addr); client->fd = accept(listener->fd, (struct sockaddr *)&client->addr, &len); dispatch_queue_t queue = dispatch_queue_create("ru.n3b.SocketReadQueue", NULL); client->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t) client->fd, 0, queue); dispatch_source_set_event_handler(client->source, ^{ onSocketDataReceived(client, dispatch_source_get_data(client->source)); });
chime_object_t* file_on_read(chime_object_t* instance, chime_object_t* context, chime_object_t* function) { #ifdef PLATFORM_MAC_OS_X int descriptor; dispatch_queue_t queue; dispatch_source_t source; //chime_object_t* data_object; queue = execution_context_get_dispatch_queue(context); descriptor = file_get_file_descriptor(instance, READWRITE_DESCRIPTOR); //data_object = source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, descriptor, 0, queue); file_set_dispatch_source(instance, FILE_READ_DISPATCH_SOURCE, source); chime_object_retain(function); dispatch_source_set_event_handler(source, ^{ int fd; size_t estimated_size; ssize_t actual_size; char* buffer; chime_object_t* tagged_data; fd = dispatch_source_get_handle(source); estimated_size = dispatch_source_get_data(source) + 1; if (estimated_size <= 1) { // fprintf(stderr, "** read zero, cancelling read source\n"); dispatch_source_cancel(source); return; } //fprintf(stderr, "** estimated: %ld\n", estimated); buffer = (char*)malloc(estimated_size); assert(buffer); actual_size = read(fd, buffer, estimated_size); tagged_data = chime_tag_encode_raw_block(buffer); chime_closure_invoke_2((chime_closure_t*)function, tagged_data, chime_integer_encode(actual_size)); });
int main(void) { dispatch_test_start("Dispatch VM Pressure test"); // rdar://problem/7000945 if (!dispatch_test_check_evfilt_vm()) { test_skip("EVFILT_VM not supported"); test_stop(); return 0; } initial = time(NULL); uint64_t memsize = _dispatch_get_memory_size(); max_page_count = MIN(memsize, MAXMEM) / ALLOC_SIZE; pages = calloc(max_page_count, sizeof(char*)); vm_queue = dispatch_queue_create("VM Pressure", NULL); vm_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VM, 0, DISPATCH_VM_PRESSURE, vm_queue); dispatch_source_set_event_handler(vm_source, ^{ if (!page_count) { // Too much memory pressure already to start the test test_skip("Memory pressure at start of test"); cleanup(); } if (__sync_add_and_fetch(&handler_call_count, 1) != NOTIFICATIONS) { log_msg("Ignoring vm pressure notification\n"); interval = 1; return; } test_long("dispatch_source_get_data()", dispatch_source_get_data(vm_source), NOTE_VM_PRESSURE); int32_t i, pc = page_count + 1; for (i = 0; i < pc && pages[i]; ++i) { free(pages[i]); pages[i] = NULL; } log_msg("Freed %ldMB\n", pg2mb(i)); });
static VALUE rb_source_get_data(VALUE self, SEL sel) { return LONG2NUM(dispatch_source_get_data(RSource(self)->source)); }
extern "C" void cxx_dispatch_proc_lambda(void) { dispatch_source_t proc_native; int res; pid_t pid; MU_BEGIN_TEST(cxx_dispatch_proc_lambda); // Creates a process and register multiple observers. Send a signal, // exit the process, etc., and verify all observers were notified. // // Simple child process that sleeps 2 seconds. // posix_spawnattr_t attr; res = posix_spawnattr_init(&attr); MU_ASSERT_TRUE( res ); res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED); MU_ASSERT_TRUE( res ); char* args[] = { (char*)"/bin/sleep", (char*)"2", NULL }; res = posix_spawnp(&pid, args[0], NULL, &attr, args, NULL); if (res < 0) { perror(args[0]); exit(127); } res = posix_spawnattr_destroy(&attr); MU_ASSERT_TRUE( res ); xdispatch::queue* completion = new xdispatch::queue("completion"); MU_ASSERT_TRUE(pid > 0); // // Suspend the "completion" queue when each observer is created. // Each observer resumes the queue when the child process exits. // If the queue is resumed too few times (indicating that not all // observers received the exit event) then the test case will not exit // within the alloted time and result in failure. // int i; for (i = 0; i < PID_CNT; ++i) { completion->suspend(); proc_native = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, dispatch_get_main_queue()); xdispatch::source* proc = new xdispatch::source( new xdispatch::native_source(proc_native) ); MU_DESC_ASSERT_NOT_NULL("DISPATCH_SOURCE_TYPE_PROC", proc); proc->handler([=]{ long flags = dispatch_source_get_data( proc->native_source() ); MU_DESC_ASSERT_EQUAL("DISPATCH_PROC_EXIT", flags, DISPATCH_PROC_EXIT); event_cnt++; completion->resume(); }); proc->resume(); } // // The completion block will be pending on the completion queue until it // has been fully resumed, at which point the test will exit successfully. // completion->async([=]{ int status; int res2 = waitpid(pid, &status, 0); MU_ASSERT_TRUE(res2 != -1); MU_DESC_ASSERT_EQUAL("Sub-process exited", WEXITSTATUS(status) | WTERMSIG(status), 0); MU_DESC_ASSERT_EQUAL("Event count", event_cnt, PID_CNT); MU_PASS(""); }); kill(pid, SIGCONT); xdispatch::exec(); MU_FAIL("Should never reach this"); MU_END_TEST; }