DWORD WINAPI thread_proc(void*) { WNDCLASSEXW clazz = { sizeof(WNDCLASSEXW) }; clazz.lpszClassName = L"dispatch"; clazz.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; clazz.lpfnWndProc = &window_proc; ATOM atom(::RegisterClassExW(&clazz)); HWND window(::CreateWindowW(reinterpret_cast<const wchar_t*>(atom), L"Dispatch Windows", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, 0, nullptr)); test_ptr_notnull("window", window); HWND button(::CreateWindowW(L"BUTTON", L"OK", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 10, 10, 100, 100, window, NULL, 0, nullptr)); test_ptr_notnull("button", button); ::ShowWindow(window, SW_SHOW); ::UpdateWindow(window); MSG msg = { 0 }; while(BOOL rv = ::GetMessageW(&msg, NULL, 0, 0)) { if(rv == -1) { return 0; } if(msg.message == dispatch_get_thread_window_message()) { dispatch_thread_queue_callback(); continue; } ::TranslateMessage(&msg); ::DispatchMessageW(&msg); } return static_cast<DWORD>(msg.wParam); }
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); } });
int main() { dispatch_queue_t q[PRIORITIES]; int i; #if USE_SET_TARGET_QUEUE test_start("Dispatch Priority (Set Target Queue)"); for(i = 0; i < PRIORITIES; i++) { q[i] = dispatch_queue_create(labels[i], NULL); test_ptr_notnull("q[i]", q[i]); assert(q[i]); dispatch_set_target_queue(as_do(q[i]), dispatch_get_global_queue(priorities[i], 0)); dispatch_queue_set_width(q[i], DISPATCH_QUEUE_WIDTH_MAX_LOGICAL_CPUS); } #else test_start("Dispatch Priority"); for(i = 0; i < PRIORITIES; i++) { q[i] = dispatch_get_global_queue(priorities[i], 0); } #endif for(i = 0; i < PRIORITIES; i++) { submit_work(q[i], &counts[i].count); } dispatch_main(); }
void test_timer(void) { dispatch_test_start("Dispatch Update Timer"); dispatch_queue_t main_q = dispatch_get_main_queue(); //test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue()); __block int i = 0; struct timeval start_time; gettimeofday(&start_time, NULL); dispatch_source_t s = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, main_q); test_ptr_notnull("dispatch_source_create", s); dispatch_source_set_timer(s, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC), NSEC_PER_SEC, 0); dispatch_source_set_cancel_handler(s, ^{ struct timeval end_time; gettimeofday(&end_time, NULL); // Make sure we actually managed to adjust the interval // duration. Seven one second ticks would blow past // this. test_long_less_than("total duration", end_time.tv_sec - start_time.tv_sec, 3); test_stop(); dispatch_release(s); });
int main(int argc, char* argv[]) { // interval is 1/10th of a second uint64_t interval = NSEC_PER_SEC / 10; // for 25 seconds struct timeval now_tv; struct timespec now_ts; interval_d = (double)interval / (double)NSEC_PER_SEC; target = (unsigned int)(25 / interval_d); test_start("Timer drift test"); timeBeginPeriod(1); timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); test_ptr_notnull("DISPATCH_SOURCE_TYPE_TIMER", timer); dispatch_source_set_event_handler_f(timer, timer_handler); gettimeofday(&now_tv, NULL); now_ts.tv_sec = now_tv.tv_sec; now_ts.tv_nsec = now_tv.tv_usec * NSEC_PER_USEC; dispatch_source_set_timer(timer, dispatch_walltime(&now_ts, interval), interval, 0); dispatch_resume(as_do(timer)); dispatch_main(); return 0; }
int main(void) { test_start("Dispatch Suspend Timer"); dispatch_queue_t main_q = dispatch_get_main_queue(); test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue()); __block int i = 0; __block int j = 0; dispatch_source_attr_t attr = dispatch_source_attr_create(); test_ptr_notnull("dispatch_source_attr_create", attr); dispatch_source_attr_set_finalizer(attr, ^(dispatch_source_t ds) { test_ptr_notnull("finalizer ran", ds); if (ds == tweedledum) test_stop(); });
void fini(void *cxt) { test_ptr_notnull("finalizer ran", cxt); if (cxt == tweedledum) { test_stop(); } }
int main(void) { dispatch_queue_t q = dispatch_get_main_queue(); test_start("Dispatch (Public) API"); test_ptr_notnull("dispatch_get_main_queue", q); dispatch_async_f(dispatch_get_main_queue(), NULL, work); dispatch_main(); }
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 cancel_handler(void* context) { struct timeval end_time; UNREFERENCED_PARAMETER(context); gettimeofday(&end_time, NULL); // Make sure we actually managed to adjust the interval // duration. Seven one second ticks would blow past // this. test_long_less_than("total duration", end_time.tv_sec - start_time.tv_sec, 3); test_ptr_notnull("finalizer ran", timer); test_stop(); }
int main(void) { test_start("Dispatch Apply"); volatile __block int32_t count = 0; const int32_t final = 32; dispatch_queue_t queue = dispatch_get_global_queue(0, 0); test_ptr_notnull("dispatch_get_concurrent_queue", queue); dispatch_apply(final, queue, ^(size_t i __attribute__((unused))) { dispatch_atomic_inc(&count); });
void test_timer(void) { dispatch_test_start("Dispatch Source Timer, bit 31"); dispatch_queue_t main_q = dispatch_get_main_queue(); //test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue()); struct timeval start_time; static dispatch_source_t s; s = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, main_q); test_ptr_notnull("dispatch_source_create", s); dispatch_source_set_timer(s, dispatch_time(DISPATCH_TIME_NOW, 0x80000000ull), 0x80000000ull, 0); gettimeofday(&start_time, NULL); dispatch_source_set_event_handler(s, ^{ dispatch_source_cancel(s); });
void test_timer(void) { dispatch_test_start("Dispatch Suspend Timer"); dispatch_queue_t main_q = dispatch_get_main_queue(); //test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue()); __block int i = 0, i_prime = 0; __block int j = 0; tweedledee = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, main_q); test_ptr_notnull("dispatch_source_timer_create", tweedledee); dispatch_source_set_timer(tweedledee, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC), NSEC_PER_SEC, 0); dispatch_source_set_cancel_handler(tweedledee, ^ { dispatch_release(tweedledee); });
int main(void) { dispatch_queue_t main_q; test_start("Dispatch Update Timer"); main_q = dispatch_get_main_queue(); test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue()); timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, main_q); dispatch_source_set_timer(timer, 1000000000ull, 0, 0); dispatch_source_set_cancel_handler_f(timer, cancel_handler); dispatch_source_set_event_handler_f(timer, event_handler); test_ptr_notnull("dispatch_source_timer_create", timer); gettimeofday(&start_time, NULL); dispatch_resume(as_do(timer)); dispatch_main(); }
int main(void) { test_start("Dispatch Update Timer"); dispatch_queue_t main_q = dispatch_get_main_queue(); test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue()); __block int i = 0; struct timeval start_time; gettimeofday(&start_time, NULL); dispatch_source_attr_t attr = dispatch_source_attr_create(); dispatch_source_attr_set_finalizer(attr, ^(dispatch_source_t ds) { struct timeval end_time; gettimeofday(&end_time, NULL); // Make sure we actually managed to adjust the interval // duration. Seven one second ticks would blow past // this. test_long_less_than("total duration", end_time.tv_sec - start_time.tv_sec, 3); test_ptr_notnull("finalizer ran", ds); test_stop(); });
int main(void) { test_start("Dispatch Queue Finalizer"); #ifdef __LP64__ ctxt_magic = (void*)((uintptr_t)arc4random() << 32 | arc4random()); #else ctxt_magic = (void*)arc4random(); #endif dispatch_queue_t q = dispatch_queue_create(NULL, NULL); test_ptr_notnull("dispatch_queue_new", q); dispatch_set_context(q, ctxt_magic); dispatch_set_finalizer_f(q, finalizer); dispatch_release(q); dispatch_main(); return 0; }
int main(void) { test_start("Dispatch Source Timer, bit 31"); dispatch_queue_t main_q = dispatch_get_main_queue(); test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue()); __block int i = 0; struct timeval start_time; gettimeofday(&start_time, NULL); dispatch_source_attr_t attr = dispatch_source_attr_create(); dispatch_source_attr_set_finalizer(attr, ^(dispatch_source_t ds) { struct timeval end_time; gettimeofday(&end_time, NULL); test_ptr_notnull("finalizer ran", ds); // XXX: check, s/b 2.0799... seconds, which is <4 seconds // when it could end on a bad boundry. test_long_less_than("needs to finish faster than 4 seconds", end_time.tv_sec - start_time.tv_sec, 4); // And it has to take at least two seconds... test_long_less_than("can't finish faster than 2 seconds", 1, end_time.tv_sec - start_time.tv_sec); test_stop(); });
int main(void) { dispatch_test_start("Dispatch Queue Finalizer"); #ifdef __LP64__ ctxt_magic = (void*)((uintptr_t)arc4random() << 32 | arc4random()); #else ctxt_magic = (void*)arc4random(); #endif // we need a non-NULL value for the tests to work properly if (ctxt_magic == NULL) { ctxt_magic = &ctxt_magic; } dispatch_queue_t q = dispatch_queue_create("com.apple.testing.finalizer", NULL); test_ptr_notnull("dispatch_queue_new", q); dispatch_set_finalizer_f(q, finalize); dispatch_queue_t q_null_context = dispatch_queue_create("com.apple.testing.finalizer.context_null", NULL); dispatch_set_context(q_null_context, NULL); dispatch_set_finalizer_f(q_null_context, never_call); dispatch_release(q_null_context); // Don't test k dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC), dispatch_get_main_queue(), ^{ // Usign async to set the context helps test that blocks are // run before the release as opposed to just thrown away. dispatch_async(q, ^{ dispatch_set_context(q, ctxt_magic); }); dispatch_release(q); });
void never_call(void *ctxt) { test_ptr_notnull("never_call should not run", NULL); test_ptr("correct context", ctxt, NULL); }