附個人工作程式碼 條件變數深度運用、互斥鎖+訊號量

一匹夫發表於2020-10-03

列一個我在工作上寫的程式碼片段, 下面是消費者端的程式碼

static void input_status_report_thread(struct local_pthread_wrapper* thread, void* param)
{
    struct input_manager *input = NULL;
    struct input_mode_lister *l = NULL;

    struct input_dev_param down_dev_param = {0};
    struct input_dev_param up_app_param = {0};
    struct input_manager_var *im_var = (struct input_manager_var *)param;

    down_dev_param.input_events = malloc(sizeof(struct input_dev_param) * MAX_INPUT_EVENT_COUNT);
    if(down_dev_param.input_events == NULL)
        log_e("malloc ");
    
    im_var->is_running  = 1;

    pthread_mutex_init(&(down_dev_param.queue_lock), NULL);
    pthread_cond_init(&(down_dev_param.queue_ready), NULL);

    down_dev_param.fifo_it = alloc_fifo_iterator(down_dev_param.input_events,
                                                 sizeof(struct input_dev_param),
                                                 MAX_INPUT_EVENT_COUNT);while (im_var->is_running) {

        pthread_mutex_lock(&down_dev_param.queue_lock);

        list_for_each_entry(l, &unlock_mode_list, node) {
            input = l->dev_t;
           
            if (input->notify_status) {    
                input->notify_status(&down_dev_param);
            }
        }

        if (fifo_empty(down_dev_param.fifo_it)) {
            log_i("等待下次事件\n");  

            //pthread_cond_wait中的mutex用於保護條件變數,
            //    呼叫這個函式等待條件的滿足(或稱呼為釋放), 此時,mutex會被自動釋放,以供其它執行緒(生產者)改變條件

            //條件變數進入wait的時候,預設內部先對mutex解鎖,以供生產者訪問,  
            //wait返回後(也就是生產者生產了新資料後, 此時輪到消費者去消費了)又會內部重新加鎖,保證消費者獨佔該佇列(共享資源)
            pthread_cond_wait(&down_dev_param.queue_ready, &down_dev_param.queue_lock);
        }

        while (!fifo_empty(down_dev_param.fifo_it)) {
            
            fifo_dequeue(down_dev_param.fifo_it, &up_app_param);//訪問完上述佇列,解鎖。 交還資源許可權給生產者.
            pthread_mutex_unlock(&down_dev_param.queue_lock);
       
            //then we need to deal the events...    
            input_report_cb listener_by_CurSYSMode = NULL;
            
            list_for_each_entry(l, &im_var->list, node) {
                listener_by_CurSYSMode = (input_report_cb)l->dev_t;
                if (listener_by_CurSYSMode) {
                    listener_by_CurSYSMode(&up_app_param);
        
                }else {
                    log_w("listener_by_CurSYSMode NULL!\n");
                }
            }

            memset(&up_app_param, 0x00, sizeof(struct input_dev_param) );  

            //下一步如果佇列還有資料,又會出隊(即訪問佇列)。
            //因為有可能再次訪問佇列,所以這裡先上鎖!!
            pthread_mutex_lock(&down_dev_param.queue_lock);

        } /* end of while(!fifo_empty ...) */

        pthread_mutex_unlock(&down_dev_param.queue_lock);

    } /* end of while(1) */

    pthread_cond_destroy(&(down_dev_param.queue_ready));
    pthread_mutex_destroy(&(down_dev_param.queue_lock));

    log_e("input_status_report_thread\n");
    pthread_exit(0);
}

對條件變數的理解:

pthread_cond_wait中的mutex用於保護條件變數,
呼叫這個函式進行wait,等待條件的滿足(或稱呼為釋放), 此時,預設內部先對mutex解鎖,以供以供生產者訪問。
  
wait返回後(也就是生產者生產了新資料後, 此時輪到消費者去消費了)又會內部重新加鎖,保證消費者獨佔該佇列(共享資源),
接著
,訪問完共享資源後,還需要進行互斥鎖的解鎖,這是交還資源許可權給生產者,以便後續生產者可以繼續生產。

 

順便貼一下生產者端的程式碼片段:

    if (up_keycode_status_param && (__is_key_report_enable(flag_nofify))) {
        /* The release key is report any time */
        if (!flag_wakeup) {
            
            pthread_mutex_lock(&up_keycode_status_param->queue_lock);

            up_keycode_status_param->input_type = INPUT_KEY;
            up_keycode_status_param->param.key_code = keycode;
            up_keycode_status_param->param.key_value = keyvalue;

            ret = fifo_enqueue(up_keycode_status_param->fifo_it, up_keycode_status_param);

            pthread_cond_signal(&up_keycode_status_param->queue_ready);

            pthread_mutex_unlock(&up_keycode_status_param->queue_lock);
            
            log_w("====notify the input manager thread, key detected!====\n");

        } else {
            /* if wakeup not wake up the input manager thread */
            flag_wakeup = 0;
        }
    }

 

 

#

1.生產者釋放條件變數以後,並不一定會立馬切換到消費者程式碼去執行,有可能是繼續執行生產者釋放條件變數後的程式碼。     

2.使用互斥鎖+訊號量的方式,執行緒A釋放訊號量以後,也不一定立馬會切換到原先就在等待該訊號量的執行緒B去執行。         

這倆操作,這點的效果是一樣的。

 

 

 

 

 

 

 

.

相關文章