• UNIX环境高级编程11.6.4条件变量


    YRZEFM`ABVG_41{]5T%J[}3

    X_CZI6%]}3PICL$%BI8R@6V

    }9AXKXASCQ7QRCFFIEJ@$OW

    LMVPMT9NKWZO(5XD%{[$93R

    #include <pthread.h>
    
    struct msg {
        struct msg *m_next;
        /* ... more stuff here ... */
        int m_id;
    };
    
    msg* workq;
    pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
    
    void process_msg(void)
    {
        msg* mp;
    
        for ( ; ; )
        {
            pthread_mutex_lock(&qlock);
            while (workq == NULL)
            {
                pthread_cond_wait(&qready, &qlock);
            }
            mp = workq;
            workq = mp->m_next;
            pthread_mutex_unlock(&qlock);
            /* now process the message mp */
        }
    }
    
    void enqueue_msg(msg* mp)
    {
        pthread_mutex_lock(&qlock);
        mp->m_next = workq;
        workq = mp;
        pthread_mutex_unlock(&qlock);
        pthread_cond_signal(&qready);
    }
    
    // threads/condvar.c 11-9
    #include <stdlib.h>
    // #include <stdio.h>
    // #include <string.h>
    // #include <unistd.h>
    #include <pthread.h>
    #include "apue.h"
    
    struct job {
        job(pthread_t threadid): j_id(threadid)
        {
            memset((char*)this + sizeof(pthread_t), 0,
                    sizeof(job) - sizeof(pthread_t));
        }
        pthread_t   j_id;   /* tells which thread handles this job */
        struct job *j_next;
        struct job *j_prev;
        /* ... more stuff here ... */
        bool        finished;
    };
    
    struct queue {
        job*            q_head;
        job*            q_tail;
        pthread_mutex_t q_lock;
        pthread_cond_t  q_cond;
    };
    
    /*
     * Initialize a queue.
     */
    int queue_init(struct queue *qp)
    {
        int err;
    
        qp->q_head = NULL;
        qp->q_tail = NULL;
        err = pthread_mutex_init(&qp->q_lock, NULL);
        if (err != 0)
            return(err);
    
        err = pthread_cond_init(&qp->q_cond, NULL);
        if (err != 0)
            return(err);
        /* ... continue initialization ... */
    
        return(0);
    }
    
    /*
     * Insert a job at the head of the queue.
     */
    void job_insert(struct queue *qp, struct job *jp)
    {
        pthread_mutex_lock(&qp->q_lock);
        jp->j_next = qp->q_head;
        jp->j_prev = NULL;
        if (qp->q_head != NULL)
            qp->q_head->j_prev = jp;
        else
            qp->q_tail = jp;	/* list was empty */
        qp->q_head = jp;
        pthread_mutex_unlock(&qp->q_lock);
    }
    
    /*
     * Append a job on the tail of the queue.
     */
    void job_append(struct queue *qp, struct job *jp)
    {
        pthread_mutex_lock(&qp->q_lock);
        printf("%ld %s write lock
    ", pthread_self(), __FUNCTION__);
        fflush(stdout);
        jp->j_next = NULL;
        jp->j_prev = qp->q_tail;
        if (qp->q_tail != NULL)
        {
            qp->q_tail->j_next = jp;
        }
        else
        {
            qp->q_head = jp;	/* list was empty */
        }
        qp->q_tail = jp;
        pthread_mutex_unlock(&qp->q_lock);
        printf("%ld %s unlock
    ", pthread_self(), __FUNCTION__);
        fflush(stdout);
        pthread_cond_signal(&qp->q_cond);
    }
    
    /*
     * Remove the given job from a queue.
     */
    void job_remove(struct queue *qp, struct job *jp)
    {
        pthread_mutex_lock(&qp->q_lock);
        printf("%ld %s write lock
    ", pthread_self(), __FUNCTION__);
        fflush(stdout);
        if (jp == qp->q_head)
        {
            qp->q_head = jp->j_next;
            if (qp->q_tail == jp)
            {
                qp->q_tail = NULL;
            }
            else
            {
                jp->j_next->j_prev = jp->j_prev;
            }
        } else if (jp == qp->q_tail)
        {
            qp->q_tail = jp->j_prev;
            jp->j_prev->j_next = jp->j_next;
        }
        else
        {
            jp->j_prev->j_next = jp->j_next;
            jp->j_next->j_prev = jp->j_prev;
        }
        pthread_mutex_unlock(&qp->q_lock);
        printf("%ld %s unlock
    ", pthread_self(), __FUNCTION__);
        fflush(stdout);
    }
    
    /*
     * Find a job for the given thread ID.
     */
    job* job_find(struct queue *qp, pthread_t id)
    {
        struct job *jp;
    
        if (pthread_mutex_lock(&qp->q_lock) != 0)
        {
            return(NULL);
        }
        printf("%ld %s read lock
    ", pthread_self(), __FUNCTION__);
        fflush(stdout);
    
        for (jp = qp->q_head; jp != NULL; jp = jp->j_next)
        {
            if (pthread_equal(jp->j_id, id))
            {
                break;
            }
        }
    
        pthread_mutex_unlock(&qp->q_lock);
        printf("%ld %s unlock
    ", pthread_self(), __FUNCTION__);
        fflush(stdout);
        return(jp);
    }
    
    void DoSomeWork(job* pJob)
    {
        pthread_t threadid = pthread_self();
        printf("%ld DoSomeWork threadid 
    ", threadid);
        fflush(stdout);
        pJob->finished = true;
        usleep(10);
    }
    
    void* thr_fn(void* arg)
    {
        pthread_t threadid = pthread_self();
        printf("%ld thread start threadid 
    ", threadid);
        fflush(stdout);
        int job_done = 0;
        job* pJob;
        for ( ; ; )
        {
            printf("%ld begin job finding 
    ", threadid);
            fflush(stdout);
            pJob = job_find(static_cast<queue*>(arg), threadid);
            if (NULL == pJob)
            {   // without the condtion, I have to do a lot of query, testing if pJob is NULL
                // not I could just wait for the condition, and then invoke the job_find method
                pthread_mutex_lock(&static_cast<queue*>(arg)->q_lock);
                pthread_cond_wait(&static_cast<queue*>(arg)->q_cond, &static_cast<queue*>(arg)->q_lock);
                pthread_mutex_unlock(&static_cast<queue*>(arg)->q_lock);
            }
            else
            {
                printf("%ld job found 
    ", threadid);
                fflush(stdout);
                DoSomeWork(pJob);
                printf("%ld %d job done 
    ", threadid, job_done + 1);
                fflush(stdout);
                job_remove(static_cast<queue*>(arg), pJob);
                if (50000 == ++job_done)
                {
                    break; // thread has do 5 job, thread return;
                }
            }
        }
        printf("%ld I have finised %d job , returning threadid 
    ", threadid, job_done);
        fflush(stdout);
        return((void *)0);
    }
    
    int main()
    {
        pthread_t threadid0;
        pthread_t threadid1;
        void* ret;
        int err;
        queue queue0;
    
        queue_init(&queue0);
    
        err = pthread_create(&threadid0, NULL, thr_fn, static_cast<void*>(&queue0));
        if (0 != err)
            err_quit("can't create thread: %s
    ", strerror(err));
    
        err = pthread_create(&threadid1, NULL, thr_fn, static_cast<void*>(&queue0));
        if (0 != err)
            err_quit("can't create thread: %s
    ", strerror(err));
    
        for (int i = 0; i < 100000; i++)
        {
            job* pJob;
            if (0 == i % 2)
            {
                pJob = new job(threadid0);
            }
            else
            {
                pJob = new job(threadid1);
            }
            usleep(100);
            job_append(&queue0, pJob);
        }
    
        printf("begin pthread_join thread0 
    ");
        err = pthread_join(threadid0, &ret);
        if (err != 0)
            err_quit("can't join with thread 0: %s
    ", strerror(err));
        printf("thread 0 exit code %d
    ", (int)(long)ret);
    
        printf("begin pthread_join thread1 
    ");
        err = pthread_join(threadid1, &ret);
        if (err != 0)
            err_quit("can't join with thread 1: %s
    ", strerror(err));
        printf("thread 1 exit code %d
    ", (int)(long)ret);
        printf("main thread exiting
    ");
        return 0;
    }
    

    GK[IP~9S$N{APVVY$]F$)LV

    `)VM)0$OJ%Y9Z}A~P1$NW_A

    我没有完全使用msg,这个例子,我修改了读写锁的例子来完成,条件变量的例子

    bestc2a78801-142e-4bc8-8869-591344381feec7ff8431-b25f-4ba2-a405-631742f87325

  • 相关阅读:
    C# .net 中文简体繁体转换
    关于html+js将值传输到后端C#的问题(删减版)
    Error mapping types
    Vs编译时RazorTagHelper
    Sum All Numbers in a Range-freecodecamp算法题目
    Caesars Cipher-freecodecamp算法题目
    Where do I belong-freecodecamp算法题目
    Seek and Destroy-freecodecamp算法题目
    Falsy Bouncer-freecodecamp算法题目
    Mutations-freecodecamp算法题目
  • 原文地址:https://www.cnblogs.com/sunyongjie1984/p/4282042.html
Copyright © 2020-2023  润新知