void pn_selector_remove(pn_selector_t *selector, pn_selectable_t *selectable) { assert(selector); assert(selectable); int idx = pni_selectable_get_index(selectable); assert(idx >= 0); iocpdesc_t *iocpd = (iocpdesc_t *) pn_list_get(selector->iocp_descriptors, idx); if (iocpd) { if (selector->current_triggered == iocpd) selector->current_triggered = iocpd->triggered_list_next; interests_update(iocpd, 0); deadlines_update(iocpd, 0); assert(selector->triggered_list_head != iocpd && !iocpd->triggered_list_prev); assert(selector->deadlines_head != iocpd && !iocpd->deadlines_prev); iocpd->selector = NULL; iocpd->selectable = NULL; } pn_list_del(selector->selectables, idx, 1); pn_list_del(selector->iocp_descriptors, idx, 1); size_t size = pn_list_size(selector->selectables); for (size_t i = idx; i < size; i++) { pn_selectable_t *sel = (pn_selectable_t *) pn_list_get(selector->selectables, i); pni_selectable_set_index(sel, i); } pni_selectable_set_index(selectable, -1); if (selector->current >= (size_t) idx) { selector->current--; } }
pn_socket_t pni_iocp_end_accept(iocpdesc_t *ld, sockaddr *addr, socklen_t *addrlen, bool *would_block, pn_error_t *error) { if (!is_listener(ld)) { set_iocp_error_status(error, PN_ERR, WSAEOPNOTSUPP); return INVALID_SOCKET; } if (ld->read_closed) { set_iocp_error_status(error, PN_ERR, WSAENOTSOCK); return INVALID_SOCKET; } if (pn_list_size(ld->acceptor->accepts) == 0) { if (ld->events & PN_READABLE && ld->iocp->iocp_trace) iocp_log("listen socket readable with no available accept completions\n"); *would_block = true; return INVALID_SOCKET; } accept_result_t *result = (accept_result_t *) pn_list_get(ld->acceptor->accepts, 0); pn_list_del(ld->acceptor->accepts, 0, 1); if (!pn_list_size(ld->acceptor->accepts)) pni_events_update(ld, ld->events & ~PN_READABLE); // No pending accepts pn_socket_t accept_sock; if (result->base.status) { accept_sock = INVALID_SOCKET; pni_win32_error(ld->error, "accept failure", result->base.status); if (ld->iocp->iocp_trace) iocp_log("%s\n", pn_error_text(ld->error)); // App never sees this socket so close it here. pni_iocp_begin_close(result->new_sock); } else { accept_sock = result->new_sock->socket; // AcceptEx special setsockopt: setsockopt(accept_sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&ld->socket, sizeof (SOCKET)); if (addr && addrlen && *addrlen > 0) { sockaddr_storage *local_addr = NULL; sockaddr_storage *remote_addr = NULL; int local_addrlen, remote_addrlen; LPFN_GETACCEPTEXSOCKADDRS fn = ld->acceptor->fn_get_accept_ex_sockaddrs; fn(result->address_buffer, 0, IOCP_SOCKADDRMAXLEN, IOCP_SOCKADDRMAXLEN, (SOCKADDR **) &local_addr, &local_addrlen, (SOCKADDR **) &remote_addr, &remote_addrlen); *addrlen = pn_min(*addrlen, remote_addrlen); memmove(addr, remote_addr, *addrlen); } } if (accept_sock != INVALID_SOCKET) { // Connected. result->new_sock->read_closed = false; result->new_sock->write_closed = false; } // Done with the completion result, so reuse it result->new_sock = NULL; begin_accept(ld->acceptor, result); return accept_sock; }
bool pn_list_remove(pn_list_t *list, void *value) { assert(list); ssize_t idx = pn_list_index(list, value); if (idx < 0) { return false; } else { pn_list_del(list, idx, 1); } return true; }
static void test_list_refcount(size_t capacity) { void *one = pn_class_new(PN_OBJECT, 0); void *two = pn_class_new(PN_OBJECT, 0); void *three = pn_class_new(PN_OBJECT, 0); void *four = pn_class_new(PN_OBJECT, 0); pn_list_t *list = pn_list(PN_OBJECT, 0); assert(!pn_list_add(list, one)); assert(!pn_list_add(list, two)); assert(!pn_list_add(list, three)); assert(!pn_list_add(list, four)); assert(pn_list_get(list, 0) == one); assert(pn_list_get(list, 1) == two); assert(pn_list_get(list, 2) == three); assert(pn_list_get(list, 3) == four); assert(pn_list_size(list) == 4); assert(pn_refcount(one) == 2); assert(pn_refcount(two) == 2); assert(pn_refcount(three) == 2); assert(pn_refcount(four) == 2); pn_list_del(list, 1, 2); assert(pn_list_size(list) == 2); assert(pn_refcount(one) == 2); assert(pn_refcount(two) == 1); assert(pn_refcount(three) == 1); assert(pn_refcount(four) == 2); assert(pn_list_get(list, 0) == one); assert(pn_list_get(list, 1) == four); assert(!pn_list_add(list, one)); assert(pn_list_size(list) == 3); assert(pn_refcount(one) == 3); pn_decref(list); assert(pn_refcount(one) == 1); assert(pn_refcount(two) == 1); assert(pn_refcount(three) == 1); assert(pn_refcount(four) == 1); pn_decref(one); pn_decref(two); pn_decref(three); pn_decref(four); }
static void test_list(size_t capacity) { pn_list_t *list = pn_list(PN_WEAKREF, 0); assert(pn_list_size(list) == 0); assert(!pn_list_add(list, (void *) 0)); assert(!pn_list_add(list, (void *) 1)); assert(!pn_list_add(list, (void *) 2)); assert(!pn_list_add(list, (void *) 3)); assert(pn_list_get(list, 0) == (void *) 0); assert(pn_list_get(list, 1) == (void *) 1); assert(pn_list_get(list, 2) == (void *) 2); assert(pn_list_get(list, 3) == (void *) 3); assert(pn_list_size(list) == 4); pn_list_del(list, 1, 2); assert(pn_list_size(list) == 2); assert(pn_list_get(list, 0) == (void *) 0); assert(pn_list_get(list, 1) == (void *) 3); pn_decref(list); }
static void drain_zombie_completions(iocp_t *iocp) { // No more pn_selector_select() from App, but zombies still need care and feeding // until their outstanding async actions complete. pni_iocp_drain_completions(iocp); // Discard any that have no pending async IO size_t sz = pn_list_size(iocp->zombie_list); for (size_t idx = 0; idx < sz;) { iocpdesc_t *iocpd = (iocpdesc_t *) pn_list_get(iocp->zombie_list, idx); if (!iocpd->ops_in_progress) { pn_list_del(iocp->zombie_list, idx, 1); sz--; } else { idx++; } } unsigned shutdown_grace = 2000; char *override = getenv("PN_SHUTDOWN_GRACE"); if (override) { int grace = atoi(override); if (grace > 0 && grace < 60000) shutdown_grace = (unsigned) grace; } pn_timestamp_t now = pn_i_now(); pn_timestamp_t deadline = now + shutdown_grace; while (pn_list_size(iocp->zombie_list)) { if (now >= deadline) break; int rv = pni_iocp_wait_one(iocp, deadline - now, NULL); if (rv < 0) { iocp_log("unexpected IOCP failure on Proton IO shutdown %d\n", GetLastError()); break; } now = pn_i_now(); } if (now >= deadline && pn_list_size(iocp->zombie_list) && iocp->iocp_trace) // Should only happen if really slow TCP handshakes, i.e. total network failure iocp_log("network failure on Proton shutdown\n"); }
static void test_map_iteration(int n) { pn_list_t *pairs = pn_list(PN_OBJECT, 2*n); for (int i = 0; i < n; i++) { void *key = pn_class_new(PN_OBJECT, 0); void *value = pn_class_new(PN_OBJECT, 0); pn_list_add(pairs, key); pn_list_add(pairs, value); pn_decref(key); pn_decref(value); } pn_map_t *map = pn_map(PN_OBJECT, PN_OBJECT, 0, 0.75); assert(pn_map_head(map) == 0); for (int i = 0; i < n; i++) { pn_map_put(map, pn_list_get(pairs, 2*i), pn_list_get(pairs, 2*i + 1)); } for (pn_handle_t entry = pn_map_head(map); entry; entry = pn_map_next(map, entry)) { void *key = pn_map_key(map, entry); void *value = pn_map_value(map, entry); ssize_t idx = pn_list_index(pairs, key); assert(idx >= 0); assert(pn_list_get(pairs, idx) == key); assert(pn_list_get(pairs, idx + 1) == value); pn_list_del(pairs, idx, 2); } assert(pn_list_size(pairs) == 0); pn_decref(map); pn_decref(pairs); }
void pn_list_clear(pn_list_t *list) { assert(list); pn_list_del(list, 0, list->size); }