TCP Socket - C Language
Riferimenti per il file pool.h
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>

Vai al codice sorgente di questo file.

Strutture dati

struct  joblist
struct  ThreadPool

Ridefinizioni di tipo (typedef)

typedef struct joblist joblist
typedef struct ThreadPool th_pool

Funzioni

th_poolpoolInit (int dim, int job_max, sigset_t *set)
int poolDispatcher (th_pool *pool, void *(*start_routine)(void *), void *arg)
int poolDestroy (th_pool *pool)

Descrizione dettagliata

Autore:
Tranchida Giulio, No Matricola 241732
Si dichiara che il contenuto di questo file e', in ogni sua parte, opera originale dell'autore.

This program is free software; you can redistribuite it and/or modify it under the terms of the GNU/General Pubblic License as published the Free software Foundation; either version 2 of the License, or (at your opinion) any later version.

Definizione nel file pool.h.


Documentazione delle ridefinizioni di tipo (typedef)

typedef struct joblist joblist

Lista dei job (a solo uso interno)

typedef struct ThreadPool th_pool

Struttura contentente le info per ogni pool di threads


Documentazione delle funzioni

th_pool* poolInit ( int  dim,
int  job_max,
sigset_t *  set 
)

poolInit

Funzione che inizializza e ritorna un Pool di Threads

Parametri:
dimDimensione del pool di threads
job_maxDimensione massima della coda dei jobs
*setOpzionale. Maschera dei segnali che il pool usera' durante la creazione dei threads. Se NULL viene ignorata.
Restituisce:
th_pool * Una nuovo pool di threads
NULL e setta errno se dim < 1

Definizione alla linea 18 del file pool.c.

                                                        {
        /* Dichiarazione della struttura che conterra' questo pool di threads */
        th_pool *pool = NULL;
        int n=0;

        if (dim<1){
                errno = EINVAL;
                sys_err(__FILE__,__LINE__,"PoolInit: dimensione del pool di thread errata");
                return NULL;
        }
        if (job_max<1){
                errno = EINVAL;
                sys_err(__FILE__,__LINE__,"PoolInit: numero massimo di job errato");
                return NULL;
        }

        /* Allocazione memoria per la struttura del pool */
        pool = (th_pool*) calloc(1, sizeof(th_pool));
        /* Setto i parametri operativi del pool */
        pool->pool_size = dim;
        pool->signalmask = set;
        pool->job_max = job_max;
        /*pool->firstjob = NULL;
        pool->lastjob = NULL;
        pool->job_size = 0;*/
        /* Creazione array dei tids dei threads */
        pool->tids = (pthread_t*) calloc(pool->pool_size, sizeof(pthread_t));

        /* Inizializzo il mutex e le cond 'notempty' e 'empty' per la lista dei job */
        if (pthread_mutex_init(&(pool->lock), NULL))
                sys_err(__FILE__,__LINE__,"PoolInit: errore pthread_mutex_init");

        if (pthread_cond_init(&(pool->notempty),NULL))
                sys_err(__FILE__,__LINE__,"PoolInit: errore pthread_cond_init notempty");

        if (pthread_cond_init(&(pool->empty),NULL))
                sys_err(__FILE__,__LINE__,"PoolInit: errore pthread_cond_init empty");

        /* Creazione dei threads */
        for (n = 0; n < pool->pool_size; n++)
                if (pthread_create(&(pool->tids[n]), NULL, &thWorker, pool) != 0){
                        sys_err(__FILE__,__LINE__,"PoolInit: errore pthread_create");
                        /* Manca una reale gestione degli errori
                         * in caso la pthread_create fallisca */
                }

        return pool;
}
int poolDispatcher ( th_pool pool,
void *(*)(void *)  start_routine,
void *  arg 
)

poolDispatcher

Funzione che sottopone un nuovo job al pool di threads

Parametri:
*poolStruttura dati del pool di thread
*(*start_routine)(void*)Il job da fare eseguire al pool
*argargomento passato al job
Restituisce:
pthread_t Il thread id a cui e' stato assegnato il job
-1 se *pool e' NULL e setta errno
-2 se *start_routine e' NULL e setta errno
-3 se fallisce l'allocazione di un nuovo job
-4 se il pool di thread e' in fase di terminazione (rifiuta il job). -5 se il numero di job attualmente pendenti nella coda e' uguale al numero massimo possibile di job in attesa.

Definizione alla linea 68 del file pool.c.

                                                                           {
        joblist * newjob = NULL;

        if (!pool){
                errno = EINVAL;
                sys_err(__FILE__,__LINE__,"Dispatch: errore pool e' nullo");
                return -1;
        }
        if (!start_routine){
                errno = EINVAL;
                sys_err(__FILE__,__LINE__,"Dispatch: errore start_routine e' nulla");
                return -2;
        }
        if (!(newjob = (struct joblist *) malloc(sizeof(struct joblist)))){
                sys_err(__FILE__,__LINE__,"Dispatch: errore malloc(sizeof(struct joblist)");
                return -3;
        }
        newjob->next = NULL;
        newjob->arg = arg;
        newjob->start_routine = start_routine;

        /* Accesso in muta esclusione alla lista dei job */
        pthread_mutex_lock(&(pool->lock));

        /* Se il pool di threads e' in fase di terminazione rifiuto il job */
        if (pool->quitflag){
                errno = ESHUTDOWN;
                sys_err(__FILE__,__LINE__,"Dispatch: errore pool di thread in fase di chiusura");
                free(newjob);
                pthread_mutex_unlock(&(pool->lock));
                return -4;
        }

        /* Se la coda di job e' piena rifiuto il nuovo job*/
        if (pool->job_size==pool->job_max){
                errno = EAGAIN;
                sys_err(__FILE__,__LINE__,"Dispatch: errore troppi job in attesa nella coda del pool");
                free(newjob);
                pthread_mutex_unlock(&(pool->lock));
                return -5;
        }

        /* lista dei jobs vuota -> inserimento in testa */
        if (pool->job_size == 0){
                pool->firstjob = newjob;
                pool->lastjob = newjob;
                /* segnalo che la coda non e' piu' vuota */
                pthread_cond_signal(&(pool->notempty));
        }
        else{   /* inserimento in coda */
                pool->lastjob->next = newjob;
                pool->lastjob = newjob;
        }
        pool->job_size++;

        pthread_mutex_unlock(&(pool->lock));
        return 0;
}
int poolDestroy ( th_pool pool)

poolDestroy

Distrugge un Pool di Threads: uccide i threads e libera le risorse
In particolare:

  • blocca la possibilita' di sottomettere un nuovo job al pool,
  • aspetta che tutti i job pendenti vengano eseguiti,
  • esegue la join di tutti i threads,
  • libera le risorse e esce.
Parametri:
*poolIl pool di threads da distruggere
Restituisce:
0 se tutto e' andato bene
-1 se *pool e' NULL e setta errno

Definizione alla linea 127 del file pool.c.

                              {
        int n=0;

        if (!pool){
                errno = EINVAL;
                sys_err(__FILE__,__LINE__,"PoolDestroy: errore pool e' nullo");
                return -1;
        }

        pthread_mutex_lock(&(pool->lock));
        /* da questo momento in poi il pool rifiutera' nuovi job */
        pool->quitflag = 1;
        /* aspetto la terminazione dei job attivi e in coda */
        while (pool->job_size != 0)
                pthread_cond_wait(&(pool->empty), &(pool->lock));

        /* termino definitivamente i threads del pool */
        pool->shutdown = 1;
        pthread_cond_broadcast(&(pool->notempty));
        pthread_mutex_unlock(&(pool->lock));

        for (n=0; n<pool->pool_size; n++){
                pthread_cond_broadcast(&(pool->notempty));
                if (pthread_join(pool->tids[n], NULL) != 0)
                        sys_err(__FILE__,__LINE__,"PoolDestroy: errore pthred_join");
        }

        /* rilascio le risorse */
        pthread_mutex_destroy(&(pool->lock));
        pthread_cond_destroy(&(pool->empty));
        pthread_cond_destroy(&(pool->notempty));
        free(pool->tids);
        free(pool);
        pool = NULL;
        return 0;
}