Exemplo n.º 1
0
static int
squash_stream_thread_func (SquashStream* stream) {
    assert (stream != NULL);

    SquashStreamPrivate* priv = stream->priv;
    SquashOperation operation;
    SquashCodec* codec = stream->codec;

    assert (priv != NULL);
    assert (codec != NULL);

    mtx_lock (&(priv->io_mtx));
    priv->result = SQUASH_OK;
    cnd_signal (&(priv->result_cnd));

    while ((operation = priv->request) == SQUASH_OPERATION_INVALID) {
        cnd_wait (&(priv->request_cnd), &(priv->io_mtx));
    }
    priv->request = SQUASH_OPERATION_INVALID;

    assert (codec->impl.splice != NULL);

    priv->result = codec->impl.splice (codec, stream->options, stream->stream_type, squash_stream_read_cb, squash_stream_write_cb, stream);
    if (priv->result == SQUASH_OK)
        priv->result = SQUASH_END_OF_STREAM;

    priv->finished = true;
    cnd_signal (&(priv->result_cnd));
    mtx_unlock (&(priv->io_mtx));

    return 0;
}
Exemplo n.º 2
0
static int physics_thread_main(void* arg)
{
    GLFWwindow* window = arg;

    for (;;)
    {
        mtx_lock(&thread_sync.particles_lock);

        // Wait for particle drawing to be done
        while (!glfwWindowShouldClose(window) &&
               thread_sync.p_frame > thread_sync.d_frame)
        {
            struct timespec ts;
            clock_gettime(CLOCK_REALTIME, &ts);
            ts.tv_nsec += 100000000;
            cnd_timedwait(&thread_sync.d_done, &thread_sync.particles_lock, &ts);
        }

        if (glfwWindowShouldClose(window))
            break;

        // Update particles
        particle_engine(thread_sync.t, thread_sync.dt);

        // Update frame counter
        thread_sync.p_frame++;

        // Unlock mutex and signal drawing thread
        mtx_unlock(&thread_sync.particles_lock);
        cnd_signal(&thread_sync.p_done);
    }

    return 0;
}
Exemplo n.º 3
0
Arquivo: db.c Projeto: jlsandell/Craft
void db_insert_block(int p, int q, int x, int y, int z, int w) {
    if (!db_enabled) {
        return;
    }
    mtx_lock(&mtx);
    ring_put_block(&ring, p, q, x, y, z, w);
    cnd_signal(&cnd);
    mtx_unlock(&mtx);
}
Exemplo n.º 4
0
/*
====================
HandleMessage
====================
*/
static void HandleMessage( const void *const arg ) {
	const server_message_t message = *( server_message_t * )arg;

	ServerInit( message.ip_socket, message.ip6_socket );

	mtx_lock( &server_mutex );
	mtx_unlock( &server_mutex );
	cnd_signal( &server_condition );
}
Exemplo n.º 5
0
Arquivo: db.c Projeto: jlsandell/Craft
void db_set_key(int p, int q, int key) {
    if (!db_enabled) {
        return;
    }
    mtx_lock(&mtx);
    ring_put_key(&ring, p, q, key);
    cnd_signal(&cnd);
    mtx_unlock(&mtx);
}
Exemplo n.º 6
0
Arquivo: db.c Projeto: jlsandell/Craft
void db_commit() {
    if (!db_enabled) {
        return;
    }
    mtx_lock(&mtx);
    ring_put_commit(&ring);
    cnd_signal(&cnd);
    mtx_unlock(&mtx);
}
Exemplo n.º 7
0
int stack10_push(Stack10 *s, int x){
	mtx_lock(&s->mtx_);
	
	while(s->vused_ >= S_SIZE){
		cnd_wait(&s->cnd_push_, &s->mtx_);
	}
	s->v_[s->vused_++] = x;

	cnd_signal(&s->cnd_pop_);
	mtx_unlock(&s->mtx_);
	return 0;
}
Exemplo n.º 8
0
int stack10_pop(Stack10 *s, int *x){
	mtx_lock(&s->mtx_);
	
	while(s->vused_ == 0){
		cnd_wait(&s->cnd_pop_, &s->mtx_);
	}
	*x = s->v_[--s->vused_];
	
	cnd_signal(&s->cnd_push_);
	mtx_unlock(&s->mtx_);
	return 0;
}
Exemplo n.º 9
0
enum pipe_error util_ringbuffer_dequeue( struct util_ringbuffer *ring,
                                         struct util_packet *packet,
                                         unsigned max_dwords,
                                         boolean wait )
{
   const struct util_packet *ring_packet;
   unsigned i;
   int ret = PIPE_OK;

   /* XXX: over-reliance on mutexes, etc:
    */
   mtx_lock(&ring->mutex);

   /* Get next ring entry:
    */
   if (wait) {
      while (util_ringbuffer_empty(ring))
         cnd_wait(&ring->change, &ring->mutex);
   }
   else {
      if (util_ringbuffer_empty(ring)) {
         ret = PIPE_ERROR_OUT_OF_MEMORY;
         goto out;
      }
   }

   ring_packet = &ring->buf[ring->tail];

   /* Both of these are considered bugs.  Raise an assert on debug builds.
    */
   if (ring_packet->dwords > ring->mask + 1 - util_ringbuffer_space(ring) ||
       ring_packet->dwords > max_dwords) {
      assert(0);
      ret = PIPE_ERROR_BAD_INPUT;
      goto out;
   }

   /* Copy data from ring:
    */
   for (i = 0; i < ring_packet->dwords; i++) {
      packet[i] = ring->buf[ring->tail];
      ring->tail++;
      ring->tail &= ring->mask;
   }

out:
   /* Signal change:
    */
   cnd_signal(&ring->change);
   mtx_unlock(&ring->mutex);
   return ret;
}
Exemplo n.º 10
0
Arquivo: db.c Projeto: jlsandell/Craft
void db_worker_stop() {
    if (!db_enabled) {
        return;
    }
    mtx_lock(&mtx);
    ring_put_exit(&ring);
    cnd_signal(&cnd);
    mtx_unlock(&mtx);
    thrd_join(thrd, NULL);
    cnd_destroy(&cnd);
    mtx_destroy(&mtx);
    ring_free(&ring);
}
Exemplo n.º 11
0
void push_synclist(SyncTileList* list,Tile* tile) {
	TileNode* node = (TileNode*)malloc(sizeof(TileNode));
	node->tile = tile;
	node->next=0;
	node->prev=0;
	mtx_lock(&list->mtx); // call from main thread..
	if (list->last==0) {
		list->first = node;
		list->last = node;
	} else {
		list->last->next = node;
		node->prev = list->last;
		list->last = node;
	}
	++list->count;
	mtx_unlock(&list->mtx);
	cnd_signal(&list->cnd);
}
Exemplo n.º 12
0
static void rd_kafka_timer_schedule (rd_kafka_timers_t *rkts,
				     rd_kafka_timer_t *rtmr, int extra_us) {
	rd_kafka_timer_t *first;

	/* Timer has been stopped */
	if (!rtmr->rtmr_interval)
		return;

	rtmr->rtmr_next = rd_clock() + rtmr->rtmr_interval + extra_us;

	if (!(first = TAILQ_FIRST(&rkts->rkts_timers)) ||
	    first->rtmr_next > rtmr->rtmr_next) {
		TAILQ_INSERT_HEAD(&rkts->rkts_timers, rtmr, rtmr_link);
                cnd_signal(&rkts->rkts_cond);
	} else
		TAILQ_INSERT_SORTED(&rkts->rkts_timers, rtmr,
                                    rd_kafka_timer_s, rtmr_link,
				    rd_kafka_timer_cmp);
}
Exemplo n.º 13
0
static SquashStatus
squash_stream_send_to_thread (SquashStream* stream, SquashOperation operation) {
    SquashStreamPrivate* priv = stream->priv;
    SquashStatus result;

    priv->request = operation;
    cnd_signal (&(priv->request_cnd));
    mtx_unlock (&(priv->io_mtx));

    mtx_lock (&(priv->io_mtx));
    while ((result = priv->result) == SQUASH_STATUS_INVALID) {
        cnd_wait (&(priv->result_cnd), &(priv->io_mtx));
    }
    priv->result = SQUASH_STATUS_INVALID;

    if (priv->finished == true) {
        mtx_unlock (&(priv->io_mtx));
        thrd_join (priv->thread, NULL);
    }

    return result;
}
Exemplo n.º 14
0
/**
 * @brief Yield execution back to the main thread
 * @protected
 *
 * This function may only be called inside the processing thread
 * spawned for thread-based plugins.
 *
 * @param stream The stream
 * @param status Status code to return for the current request
 * @return The code of the next requested operation
 */
static SquashOperation
squash_stream_yield (SquashStream* stream, SquashStatus status) {
    SquashStreamPrivate* priv = stream->priv;
    SquashOperation operation;

    assert (stream != NULL);
    assert (priv != NULL);

    priv->request = SQUASH_OPERATION_INVALID;
    priv->result = status;

    cnd_signal (&(priv->result_cnd));
    mtx_unlock (&(priv->io_mtx));
    if (status < 0)
        thrd_exit (status);

    mtx_lock (&(priv->io_mtx));
    while ((operation = priv->request) == SQUASH_OPERATION_INVALID) {
        cnd_wait (&(priv->request_cnd), &(priv->io_mtx));
    }
    return operation;
}
Exemplo n.º 15
0
static int ctrl_thrd_main (void *arg) {


        mtx_lock(&ctrl.lock);
        while (!ctrl.term) {
                int64_t now;

                cnd_timedwait_ms(&ctrl.cnd, &ctrl.lock, 10);

                if (ctrl.cmd.ts_at) {
                        ctrl.next.ts_at = ctrl.cmd.ts_at;
                        ctrl.next.delay = ctrl.cmd.delay;
                        ctrl.cmd.ts_at = 0;
                        ctrl.cmd.ack = 1;
                        printf(_C_CYA "## %s: sockem: "
                               "receieved command to set delay "
                               "to %d in %dms\n" _C_CLR,
                               __FILE__,
                               ctrl.next.delay,
                               (int)(ctrl.next.ts_at - test_clock()) / 1000);

                }

                now = test_clock();
                if (ctrl.next.ts_at && now > ctrl.next.ts_at) {
                        assert(ctrl.skm);
                        printf(_C_CYA "## %s: "
                               "sockem: setting socket delay to %d\n" _C_CLR,
                               __FILE__, ctrl.next.delay);
                        sockem_set(ctrl.skm, "delay", ctrl.next.delay, NULL);
                        ctrl.next.ts_at = 0;
                        cnd_signal(&ctrl.cnd); /* signal back to caller */
                }
        }
        mtx_unlock(&ctrl.lock);

        return 0;
}
Exemplo n.º 16
0
bool RWMutex::unlock()
{
	bool result1 = true, result2 = true;
	if(nExclusiveAccessCount == 0)
	{
		if(mtx_lock(&mtxSharedAccessCompleted) != thrd_success)
			return false;

//		nCompletedSharedAccessCount++;
		if(++nCompletedSharedAccessCount == 0)
		{
			result1 = (cnd_signal(&cndSharedAccessCompleted) == thrd_success);
		}
		result2 = (mtx_unlock(&mtxSharedAccessCompleted) == thrd_success);
	}
	else
	{
		nExclusiveAccessCount--;
		result1 = (mtx_unlock(&mtxSharedAccessCompleted) == thrd_success);
		result2 = (mtx_unlock(&mtxExclusiveAccess) == thrd_success);
	}

	return (result1 && result2);
}
Exemplo n.º 17
0
void util_ringbuffer_enqueue( struct util_ringbuffer *ring,
                              const struct util_packet *packet )
{
   unsigned i;

   /* XXX: over-reliance on mutexes, etc:
    */
   mtx_lock(&ring->mutex);

   /* make sure we don't request an impossible amount of space
    */
   assert(packet->dwords <= ring->mask);

   /* Wait for free space:
    */
   while (util_ringbuffer_space(ring) < packet->dwords)
      cnd_wait(&ring->change, &ring->mutex);

   /* Copy data to ring:
    */
   for (i = 0; i < packet->dwords; i++) {

      /* Copy all dwords of the packet.  Note we're abusing the
       * typesystem a little - we're being passed a pointer to
       * something, but probably not an array of packet structs:
       */
      ring->buf[ring->head] = packet[i];
      ring->head++;
      ring->head &= ring->mask;
   }

   /* Signal change:
    */
   cnd_signal(&ring->change);
   mtx_unlock(&ring->mutex);
}
Exemplo n.º 18
0
static void draw_particles(GLFWwindow* window, double t, float dt)
{
    int i, particle_count;
    Vertex vertex_array[BATCH_PARTICLES * PARTICLE_VERTS];
    Vertex* vptr;
    float alpha;
    GLuint rgba;
    Vec3 quad_lower_left, quad_lower_right;
    GLfloat mat[16];
    PARTICLE* pptr;

    // Here comes the real trick with flat single primitive objects (s.c.
    // "billboards"): We must rotate the textured primitive so that it
    // always faces the viewer (is coplanar with the view-plane).
    // We:
    //   1) Create the primitive around origo (0,0,0)
    //   2) Rotate it so that it is coplanar with the view plane
    //   3) Translate it according to the particle position
    // Note that 1) and 2) is the same for all particles (done only once).

    // Get modelview matrix. We will only use the upper left 3x3 part of
    // the matrix, which represents the rotation.
    glGetFloatv(GL_MODELVIEW_MATRIX, mat);

    // 1) & 2) We do it in one swift step:
    // Although not obvious, the following six lines represent two matrix/
    // vector multiplications. The matrix is the inverse 3x3 rotation
    // matrix (i.e. the transpose of the same matrix), and the two vectors
    // represent the lower left corner of the quad, PARTICLE_SIZE/2 *
    // (-1,-1,0), and the lower right corner, PARTICLE_SIZE/2 * (1,-1,0).
    // The upper left/right corners of the quad is always the negative of
    // the opposite corners (regardless of rotation).
    quad_lower_left.x = (-PARTICLE_SIZE / 2) * (mat[0] + mat[1]);
    quad_lower_left.y = (-PARTICLE_SIZE / 2) * (mat[4] + mat[5]);
    quad_lower_left.z = (-PARTICLE_SIZE / 2) * (mat[8] + mat[9]);
    quad_lower_right.x = (PARTICLE_SIZE / 2) * (mat[0] - mat[1]);
    quad_lower_right.y = (PARTICLE_SIZE / 2) * (mat[4] - mat[5]);
    quad_lower_right.z = (PARTICLE_SIZE / 2) * (mat[8] - mat[9]);

    // Don't update z-buffer, since all particles are transparent!
    glDepthMask(GL_FALSE);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);

    // Select particle texture
    if (!wireframe)
    {
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, particle_tex_id);
    }

    // Set up vertex arrays. We use interleaved arrays, which is easier to
    // handle (in most situations) and it gives a linear memeory access
    // access pattern (which may give better performance in some
    // situations). GL_T2F_C4UB_V3F means: 2 floats for texture coords,
    // 4 ubytes for color and 3 floats for vertex coord (in that order).
    // Most OpenGL cards / drivers are optimized for this format.
    glInterleavedArrays(GL_T2F_C4UB_V3F, 0, vertex_array);

    // Wait for particle physics thread to be done
    mtx_lock(&thread_sync.particles_lock);
    while (!glfwWindowShouldClose(window) &&
            thread_sync.p_frame <= thread_sync.d_frame)
    {
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        ts.tv_nsec += 100000000;
        cnd_timedwait(&thread_sync.p_done, &thread_sync.particles_lock, &ts);
    }

    // Store the frame time and delta time for the physics thread
    thread_sync.t = t;
    thread_sync.dt = dt;

    // Update frame counter
    thread_sync.d_frame++;

    // Loop through all particles and build vertex arrays.
    particle_count = 0;
    vptr = vertex_array;
    pptr = particles;

    for (i = 0;  i < MAX_PARTICLES;  i++)
    {
        if (pptr->active)
        {
            // Calculate particle intensity (we set it to max during 75%
            // of its life, then it fades out)
            alpha =  4.f * pptr->life;
            if (alpha > 1.f)
                alpha = 1.f;

            // Convert color from float to 8-bit (store it in a 32-bit
            // integer using endian independent type casting)
            ((GLubyte*) &rgba)[0] = (GLubyte)(pptr->r * 255.f);
            ((GLubyte*) &rgba)[1] = (GLubyte)(pptr->g * 255.f);
            ((GLubyte*) &rgba)[2] = (GLubyte)(pptr->b * 255.f);
            ((GLubyte*) &rgba)[3] = (GLubyte)(alpha * 255.f);

            // 3) Translate the quad to the correct position in modelview
            // space and store its parameters in vertex arrays (we also
            // store texture coord and color information for each vertex).

            // Lower left corner
            vptr->s    = 0.f;
            vptr->t    = 0.f;
            vptr->rgba = rgba;
            vptr->x    = pptr->x + quad_lower_left.x;
            vptr->y    = pptr->y + quad_lower_left.y;
            vptr->z    = pptr->z + quad_lower_left.z;
            vptr ++;

            // Lower right corner
            vptr->s    = 1.f;
            vptr->t    = 0.f;
            vptr->rgba = rgba;
            vptr->x    = pptr->x + quad_lower_right.x;
            vptr->y    = pptr->y + quad_lower_right.y;
            vptr->z    = pptr->z + quad_lower_right.z;
            vptr ++;

            // Upper right corner
            vptr->s    = 1.f;
            vptr->t    = 1.f;
            vptr->rgba = rgba;
            vptr->x    = pptr->x - quad_lower_left.x;
            vptr->y    = pptr->y - quad_lower_left.y;
            vptr->z    = pptr->z - quad_lower_left.z;
            vptr ++;

            // Upper left corner
            vptr->s    = 0.f;
            vptr->t    = 1.f;
            vptr->rgba = rgba;
            vptr->x    = pptr->x - quad_lower_right.x;
            vptr->y    = pptr->y - quad_lower_right.y;
            vptr->z    = pptr->z - quad_lower_right.z;
            vptr ++;

            // Increase count of drawable particles
            particle_count ++;
        }

        // If we have filled up one batch of particles, draw it as a set
        // of quads using glDrawArrays.
        if (particle_count >= BATCH_PARTICLES)
        {
            // The first argument tells which primitive type we use (QUAD)
            // The second argument tells the index of the first vertex (0)
            // The last argument is the vertex count
            glDrawArrays(GL_QUADS, 0, PARTICLE_VERTS * particle_count);
            particle_count = 0;
            vptr = vertex_array;
        }

        // Next particle
        pptr++;
    }

    // We are done with the particle data
    mtx_unlock(&thread_sync.particles_lock);
    cnd_signal(&thread_sync.d_done);

    // Draw final batch of particles (if any)
    glDrawArrays(GL_QUADS, 0, PARTICLE_VERTS * particle_count);

    // Disable vertex arrays (Note: glInterleavedArrays implicitly called
    // glEnableClientState for vertex, texture coord and color arrays)
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    glDepthMask(GL_TRUE);
}
Exemplo n.º 19
0
int NetProbeServerTP(char *TCPPort, char *threadnum){

	//Create a thread pool
	cnd_init(&cond);
	mtx_init(&ThMutex, mtx_plain);
	int ThreadNum = atoi(threadnum);
	
	for (int j = 0; j < ThreadNum; j++){
		thrd_t TCPSThread;
		if (thrd_create(&TCPSThread, TPTCPChild, NULL) == thrd_error){
			printf("Create thread is failed\n");
			return 0;
		}
		else{
			printf("Creating thread %d in threadpool mode.\n", j+1);
			if (j == ThreadNum-1){
				printf("Create threadpool with %d threads in totoal.\n", j+1);
				printf("Waiting for client to connect...\n");
			}
		}
	}
	
	SOCKET Socket, new_socket;
	struct sockaddr_in server, client;
	int  recv_len;
	socklen_t c;
	c = sizeof(struct sockaddr_in);
	char *ReceiveBuf;
	ReceiveBuf = (char *)malloc(sizeof(char)* 1024);

	//Initialize Winsock
#ifdef WIN32
	WSADATA wsa;
	if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0){
		printf("Failed to Initialize, Error code : %d", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
#endif
	if ((Socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
		printf("Could not create socket : d%", WSAGetLastError());
	}
	memset(&server, 0, sizeof(struct sockaddr_in));
	memset(&client, 0, sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(atoi(TCPPort));
	if (bind(Socket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR){
		printf("Bind failed with error code : %d", WSAGetLastError());
		exit(EXIT_FAILURE);
	}
	listen(Socket, 100);
	
	//Listening to new TCP connection
	while (1){
		memset(ReceiveBuf, 0, 1024);
		if ((new_socket = accept(Socket, (struct sockaddr *)&client, &c)) == INVALID_SOCKET){
			printf("accept failed with error code: %d\n", WSAGetLastError());
			return 0;
		}
		else{
			mtx_lock(&ThMutex);
			SocketQueue.Enqueue(&SocketQueue, new_socket);
			mtx_unlock(&ThMutex);
			cnd_signal(&cond);
		}
		Sleep(2);
	}
	closesocket(Socket);
#ifdef WIN32
	WSACleanup();
#endif
	return 0;
}
Exemplo n.º 20
0
/**
 * Interrupt rd_kafka_timers_run().
 * Used for termination.
 */
void rd_kafka_timers_interrupt (rd_kafka_timers_t *rkts) {
	rd_kafka_timers_lock(rkts);
	cnd_signal(&rkts->rkts_cond);
	rd_kafka_timers_unlock(rkts);
}
Exemplo n.º 21
0
int main(int argc, char** argv)
{
    signal(SIGINT, IntHandler);

    Server serv;

    // Initialize the server
    InitConfig(&serv.conf, argv[1], argc, argv);
    
    if(!serv.conf.name) {
        fprintf(stderr, "Script doesn't specify a server name.\n");
        return 1;
    }

    if(!serv.conf.port) {
        fprintf(stderr, "Script doesn't specify a port.\n");
        return 1;
    }

	printf("Successfully configured server.\n"
		"Name: %s\n"
		"Port: %s\n"
		"Num Threads: %d\n"
		"Cycles Per Loop: %d\n"
		"Num Routes: %d\n", serv.conf.name, serv.conf.port, serv.conf.numThreads, serv.conf.cyclesPerLoop, sb_count(serv.conf.routes));

    InitList(&serv.clientQueue, sizeof(Sock));
    InitList(&serv.requestQueue, sizeof(ClientRequest));

    cnd_init(&serv.updateLoop);
    cnd_init(&serv.newConn);

    // The loop thread is responsible for initializing LoopData

    thrd_t loopThread, connThread;

    thrd_create(&loopThread, MainLoop, &serv);
    thrd_create(&connThread, ConnLoop, &serv);

    // Initialize winsock and listen for clients
    WSADATA wsaData;
    SOCKET listenSocket;

    int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if(iResult != 0) {
        fprintf(stderr, "WSAStartup failed: %d\n", iResult);
        return 1;
    }

    struct addrinfo hints;
    
    ZeroMemory(&hints, sizeof(hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    struct addrinfo* result;

    iResult = getaddrinfo(NULL, serv.conf.port, &hints, &result);
    if(iResult != 0) {
        fprintf(stderr, "getaddrinfo failed: %d\n", iResult);
        WSACleanup();
        return 1;
    }
    
    listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);

    if(listenSocket == INVALID_SOCKET) {
        fprintf(stderr, "Error at socket(): %d\n", WSAGetLastError());
        freeaddrinfo(result); 
        WSACleanup();
        return 1;
    }

    freeaddrinfo(result);

    iResult = bind(listenSocket, result->ai_addr, (int)result->ai_addrlen);

    if(iResult == SOCKET_ERROR) {
        fprintf(stderr, "bind failed with error: %d\n", WSAGetLastError());
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }

    if(listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) {
        fprintf(stderr, "listen failed with error: %d\n", WSAGetLastError());
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }
	
	while (KeepRunning) {
		SOCKET clientSocket = accept(listenSocket, NULL, NULL);

		if (clientSocket == INVALID_SOCKET) {
			fprintf(stderr, "accept failed: %d\n", WSAGetLastError());
            continue;
		}

		int iMode = 1;
        if (ioctlsocket(clientSocket, FIONBIO, &iMode) == SOCKET_ERROR) {
            fprintf(stderr, "ioctlsocket failed: %d\n", WSAGetLastError());
            continue;
        }

        Sock sock;

        InitSock(&sock, (void*)clientSocket);
        
        ListPushBack(&serv.clientQueue, &sock);

        cnd_signal(&serv.newConn);
	}

    WSACleanup();

    thrd_join(&connThread, NULL);
	thrd_join(&loopThread, NULL);

    cnd_destroy(&serv.newConn);
    cnd_destroy(&serv.updateLoop);

	DestroyList(&serv.requestQueue);
	DestroyList(&serv.clientQueue);

    DestroyConfig(&serv.conf);

	return 0;
}