Topic : Multi-Threaded Programming
Author : LUPG
Page : << Previous 14  Next >>
Go to page :


             */
#ifdef DEBUG
         printf("thread '%d' before pthread_cond_wait\n", data->thread_id);
         fflush(stdout);
#endif /* DEBUG */
     rc = pthread_cond_wait(data->got_request, data->request_mutex);
     /* and after we return from pthread_cond_wait, the mutex  */
     /* is locked again, so we don't need to lock it ourselves */
#ifdef DEBUG
         printf("thread '%d' after pthread_cond_wait\n", data->thread_id);
         fflush(stdout);
#endif /* DEBUG */
 }
    }

    /* remove thread cleanup handler. never reached, but we must use */
    /* it here, according to pthread_cleanup_push's manual page.     */
    pthread_cleanup_pop(0);
}





requests_queue.c


#include <stdlib.h>      /* malloc() and free()                       */
#include <assert.h>      /* assert()                                  */

#include "requests_queue.h"      /* requests queue functions and structs */


/*
* function init_requests_queue(): create a requests queue.
* algorithm: creates a request queue structure, initialize with given
*            parameters.
* input:     queue's mutex, queue's condition variable.
* output:    none.
*/
struct requests_queue*
init_requests_queue(pthread_mutex_t* p_mutex, pthread_cond_t*  p_cond_var)
{
    struct requests_queue* queue =
  (struct requests_queue*)malloc(sizeof(struct requests_queue));
    if (!queue) {
 fprintf(stderr, "out of memory. exiting\n");
 exit(1);
    }
    /* initialize queue */
    queue->requests = NULL;
    queue->last_request = NULL;
    queue->num_requests = 0;
    queue->p_mutex = p_mutex;
    queue->p_cond_var = p_cond_var;

    return queue;
}

/*
* function add_request(): add a request to the requests list
* algorithm: creates a request structure, adds to the list, and
*            increases number of pending requests by one.
* input:     pointer to queue, request number.
* output:    none.
*/
void
add_request(struct requests_queue* queue, int request_num)
{
    int rc;                     /* return code of pthreads functions.  */
    struct request* a_request;      /* pointer to newly added request.     */

    /* sanity check - amke sure queue is not NULL */
    assert(queue);

    /* create structure with new request */
    a_request = (struct request*)malloc(sizeof(struct request));
    if (!a_request) { /* malloc failed?? */
 fprintf(stderr, "add_request: out of memory\n");
 exit(1);
    }
    a_request->number = request_num;
    a_request->next = NULL;

    /* lock the mutex, to assure exclusive access to the list */
    rc = pthread_mutex_lock(queue->p_mutex);

    /* add new request to the end of the list, updating list */
    /* pointers as required */
    if (queue->num_requests == 0) { /* special case - list is empty */
 queue->requests = a_request;
 queue->last_request = a_request;
    }
    else {
 queue->last_request->next = a_request;
 queue->last_request = a_request;
    }

    /* increase total number of pending requests by one. */
    queue->num_requests++;

#ifdef DEBUG
    printf("add_request: added request with id '%d'\n", a_request->number);
    fflush(stdout);
#endif /* DEBUG */

    /* unlock mutex */
    rc = pthread_mutex_unlock(queue->p_mutex);

    /* signal the condition variable - there's a new request to handle */
    rc = pthread_cond_signal(queue->p_cond_var);
}

/*
* function get_request(): gets the first pending request from the requests list
*                         removing it from the list.
* algorithm: creates a request structure, adds to the list, and
*            increases number of pending requests by one.
* input:     pointer to requests queue.
* output:    pointer to the removed request, or NULL if none.
* memory:    the returned request need to be freed by the caller.
*/
struct request*
get_request(struct requests_queue* queue)
{
    int rc;                     /* return code of pthreads functions.  */
    struct request* a_request;      /* pointer to request.                 */

    /* sanity check - amke sure queue is not NULL */
    assert(queue);

    /* lock the mutex, to assure exclusive access to the list */
    rc = pthread_mutex_lock(queue->p_mutex);

    if (queue->num_requests > 0) {
 a_request = queue->requests;
 queue->requests = a_request->next;
 if (queue->requests == NULL) { /* this was last request on the list */
     queue->last_request = NULL;
 }
 /* decrease the total number of pending requests */
 queue->num_requests--;
    }
    else { /* requests list is empty */
 a_request = NULL;
    }

    /* unlock mutex */
    rc = pthread_mutex_unlock(queue->p_mutex);

    /* return the request to the caller. */
    return a_request;
}

/*
* function get_requests_number(): get the number of requests in the list.
* input:     pointer to requests queue.
* output:    number of pending requests on the queue.
*/
int
get_requests_number(struct requests_queue* queue)
{
    int rc;                     /* return code of pthreads functions.  */
    int num_requests;      /* temporary, for result.              */

    /* sanity check */
    assert(queue);

    /* lock the mutex, to assure exclusive access to the list */
    rc = pthread_mutex_lock(queue->p_mutex);

    num_requests = queue->num_requests;

    /* unlock mutex */
    rc = pthread_mutex_unlock(queue->p_mutex);

    return num_requests;
}

/*
* function delete_requests_queue(): delete a requests queue.
* algorithm: delete a request queue structure, and free all memory it uses.
* input:     pointer to requests queue.
* output:    none.
*/
void
delete_requests_queue(struct requests_queue* queue)
{
    struct request* a_request;      /* pointer to a request.               */

    /* sanity check - amke sure queue is not NULL */
    assert(queue);

    /* first free any requests that might be on the queue */
    while (queue->num_requests > 0) {
 a_request = get_request(queue);
 free(a_request);
    }

    /* finally, free the queue's struct itself */
    free(queue);
}






line-count.c


#include <stdio.h>             /* standard I/O routines                      */
#include <pthread.h>           /* pthread functions and data structures      */

#define DATA_FILE "very_large_data_file"

/* global mutex for our program. assignment initializes it. */
pthread_mutex_t action_mutex = PTHREAD_MUTEX_INITIALIZER;

/* global condition variable for our program. assignment initializes it. */
pthread_cond_t  action_cond   = PTHREAD_COND_INITIALIZER;

/* flag to denote if the user requested to cancel the operation in the middle */
/* 0 means 'no'. */
int cancel_operation = 0;

/*
* function: restore_coocked_mode - restore normal screen mode.
* algorithm: uses the 'stty' command to restore normal screen mode.
*            serves as a cleanup function for the user input thread.
* input: none.
* output: none.
*/

void
restore_coocked_mode(void* dummy)
{
#ifdef DEBUG
    printf("restore_coocked_mode: before 'stty -raw echo'\n\r");
    fflush(stdout);
#endif /* DEBUG */
    system("stty -raw echo");
#ifdef DEBUG
    printf("restore_coocked_mode: after 'stty -raw echo'\n\r");
    fflush(stdout);
#endif /* DEBUG */
}

/*
* function: read_user_input - read user input while long operation in progress.
* algorithm: put screen in raw mode (without echo), to allow for unbuffered


Page : << Previous 14  Next >>