C++11 thread 同步實例

#include <iostream>
#include <queue>
#include <optional>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <string>

struct DataInfo {
    DataInfo() = default;
    DataInfo(const std::string& accountNum, const std::string& systemId, const std::string& passWord, const std::string& channelType)
        : accountNum(accountNum), systemId(systemId), passWord(passWord), channelType(channelType) {}

    std::string accountNum{};
    std::string systemId{};
    std::string passWord{};
    std::string channelType{};
};

struct SendData {
    SendData() = default;

    std::optional<DataInfo> dataInfo;
    bool quitFlag;
};

std::mutex mtx;
std::condition_variable cv;
std::queue<SendData> que;

std::optional<DataInfo> getInputData()
{
    std::cout << "Please input data:"<< std::endl;
    std::string input = "quit";
    std::cin >> input;

    if (input == "quit") {
        return std::nullopt;
    }

    auto accountNumIndex = input.find_first_of(",");
    std::string accountNum= input.substr(0,accountNumIndex);
    input = input.substr(accountNumIndex+1,input.length());

    auto systemIdIndex = input.find_first_of(",");
    std::string systemId= input.substr(0,systemIdIndex);
    input = input.substr(systemIdIndex+1,input.length());

    auto passWordIndex = input.find_first_of(",");
    std::string passWord= input.substr(0,passWordIndex);
    input = input.substr(passWordIndex+1,input.length());

    auto channelTypeIndex = input.find_first_of(",");
    std::string channelType= input.substr(0,channelTypeIndex);
    input = input.substr(channelTypeIndex+1,input.length());

    DataInfo dataInfo{accountNum,systemId,passWord,channelType};

    return std::make_optional(dataInfo);
}

void printfInputData(std::optional<DataInfo> data)
{
    if(data != std::nullopt) {
        std::cout << data.value().accountNum << std::endl;
        std::cout << data.value().systemId << std::endl;
        std::cout << data.value().passWord << std::endl;
        std::cout << data.value().channelType << std::endl;
    }
}

void senderFunc()
{
    while(true) {
        std::unique_lock<std::mutex> lk(mtx);

        if(!que.empty()) {
            if( cv.wait_for(lk,std::chrono::seconds(6)) == std::cv_status::timeout) {
                std::cout << "senderFunc timeout." << std::endl;
            }
        }

        auto dataInfo = getInputData();
        SendData sendData{};
        if(dataInfo != std::nullopt) {
            sendData.quitFlag = false;
        }
        else {
            sendData.quitFlag = true;
        }
        sendData.dataInfo = dataInfo;
        que.push(sendData);
        std::cout << "senderFunc send input data." << std::endl;

        cv.notify_one();

        if(sendData.quitFlag) {
            std::cout << "senderFunc quit." << std::endl;
            break;
        }
    }
}

void receiverRunc()
{
    while (true) {
        std::unique_lock<std::mutex> lk(mtx);
        std::cout << "receiverRunc waiting." << std::endl;

        cv.wait(lk,[]{return !que.empty();});
        std::cout << "receive input data." << std::endl;

        auto data = que.front();
        que.pop();
        // 處理數據需要較多時間,所以先解鎖mutex
        lk.unlock();

        if(data.quitFlag) {
            std::cout << "receiverRunc quit." << std::endl;
            break;
        }
        std::cout << "process input data." << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(4));
        printfInputData(data.dataInfo);

        cv.notify_one();
    }
}

int main()
{
    std::cout << "main" << std::endl;
    std::thread thd1(senderFunc);
    std::thread thd2(receiverRunc);

    thd1.join();
    thd2.join();

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章