int worker_manager(void *data) { for(;;) { int i,j,k; waiter_wait(&manager_monitor); SDL_LockMutex(finished_gen.mutex); while (finished_gen.head != finished_gen.tail) { int h = finished_gen.head; end_procgen(gen_queue[h].world_x, gen_queue[h].world_y); put_chunk_in_cache(gen_queue[h].world_x, gen_queue[h].world_y, gen_queue[h].gc); finished_gen.head = (h+1) % finished_gen.length; } SDL_UnlockMutex(finished_gen.mutex); SDL_LockMutex(requested_mesh_mutex); for (i=0; i < MAX_BUILT_MESHES; ++i) { requested_mesh *rm = &renderer_requested_meshes[i]; if (rm->state == RMS_requested) { int valid_chunks=0; for (k=0; k < 4; ++k) { for (j=0; j < 4; ++j) { if (!rm->chunk_set_valid[k][j]) { int cx = rm->x + j * GEN_CHUNK_SIZE_X, cy = rm->y + k * GEN_CHUNK_SIZE_Y; gen_chunk_cache *gcc = get_gen_chunk_cache_for_coord(cx, cy); if (gcc) { rm->cs.chunk[k][j] = gcc->chunk; } else if (is_in_progress(cx, cy)) { // it's already in progress, so do nothing } else if (can_start_procgen(cx, cy)) { task t; start_procgen(cx,cy); t.world_x = cx; t.world_y = cy; t.task_type = JOB_generate_terrain; add_task(&t); } } else { ++valid_chunks; } } } if (valid_chunks == 16) { task t; t.cs = rm->cs; assert(rm->state == RMS_requested); rm->state = RMS_chunks_completed_waiting_for_meshing; t.task_type = JOB_build_mesh; t.world_x = rm->x; t.world_y = rm->y; add_task(&t); } } } SDL_UnlockMutex(requested_mesh_mutex); } }
/* of p. */ static word backwards_height(ptr_t p) { word result; ptr_t pred = GET_OH_BG_PTR(p); back_edges *be; if (NULL == pred) return 1; if (((word)pred & FLAG_MANY) == 0) { if (is_in_progress(p)) return 0; /* DFS back edge, i.e. we followed */ /* an edge to an object already */ /* on our stack: ignore */ push_in_progress(p); result = backwards_height(pred) + 1; pop_in_progress(p); return result; } be = (back_edges *)((word)pred & ~FLAG_MANY); if (be -> height >= 0 && be -> height_gc_no == (unsigned short)GC_gc_no) return be -> height; /* Ignore back edges in DFS */ if (be -> height == HEIGHT_IN_PROGRESS) return 0; result = (be -> height > 0? be -> height : 1); be -> height = HEIGHT_IN_PROGRESS; { back_edges *e = be; word n_edges; word total; int local = 0; if (((word)pred & FLAG_MANY) != 0) { n_edges = e -> n_edges; } else if (pred != NULL && ((word)pred & 1) == 0) { /* A misinterpreted freelist link. */ n_edges = 1; local = -1; } else { n_edges = 0; } for (total = 0; total < n_edges; ++total) { word this_height; if (local == MAX_IN) { e = e -> cont; local = 0; } if (local >= 0) pred = e -> edges[local++]; /* Execute the following once for each predecessor pred of p */ /* in the points-to graph. */ if (GC_is_marked(pred) && ((word)GET_OH_BG_PTR(p) & FLAG_MANY) == 0) { GC_COND_LOG_PRINTF("Found bogus pointer from %p to %p\n", (void *)pred, (void *)p); /* Reachable object "points to" unreachable one. */ /* Could be caused by our lax treatment of GC descriptors. */ this_height = 1; } else { this_height = backwards_height(pred); } if (this_height >= result) result = this_height + 1; } } be -> height = result; be -> height_gc_no = (unsigned short)GC_gc_no; return result; }
SOCKET mcs_connect(const char *hostname, int portnum, int *errno_out, bool blocking) { SOCKET ret = INVALID_SOCKET; struct addrinfo *ai = NULL; struct addrinfo *next = NULL; struct addrinfo hints; char port[50]; int error; if (errno_out != NULL) { *errno_out = -1; } memset(&hints, 0, sizeof(0)); hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC; snprintf(port, sizeof(port), "%d", portnum); error = getaddrinfo(hostname, port, &hints, &ai); if (error != 0) { #if 0 if (error != EAI_SYSTEM) { /* settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL, */ /* "getaddrinfo(): %s\n", gai_strerror(error)); */ } else { /* settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL, */ /* "getaddrinfo(): %s\n", strerror(error)); */ } #endif return INVALID_SOCKET; } for (next = ai; next; next = next->ai_next) { SOCKET sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == INVALID_SOCKET) { /* settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL, */ /* "Failed to create socket: %s\n", */ /* strerror(errno)); */ continue; } /* If the caller wants non-blocking, set the sock options */ /* now so even the connect() becomes non-blocking. */ if (!blocking && (mcs_set_sock_opt(sock) != MCS_SUCCESS)) { closesocket(sock); continue; } if (connect(sock, ai->ai_addr, (socklen_t)ai->ai_addrlen) == SOCKET_ERROR) { #ifdef WIN32 DWORD errno_last = WSAGetLastError(); #else int errno_last = errno; #endif if (errno_out != NULL) { *errno_out = errno_last; } if (!blocking && (is_in_progress(errno_last) || is_blocking(errno_last))) { ret = sock; break; } /* settings.extensions.logger->log(EXTENSION_LOG_WARNING, NULL, */ /* "Failed to connect socket: %s\n", */ /* strerror(errno)); */ closesocket(sock); continue; } if (mcs_set_sock_opt(sock) == MCS_SUCCESS) { ret = sock; break; } closesocket(sock); } freeaddrinfo(ai); return ret; }