如何实现两个具有输出的流,以便输出不会混淆?

问题描述 投票:0回答:1
void thread1() {
    std::string str;

    while (true) {
        {
            std::lock_guard<std::mutex> lock(io_mtx);
            std::cout << std::endl << "Enter line: ";
        }

        std::getline(std::cin, str);

        std::unique_lock<std::mutex> lock(mtx);
        if (str == "exit") break;

        if (str.size() > 64 || !std::all_of(str.begin(), str.end(), ::isdigit)) {
            {
                std::lock_guard<std::mutex> iolock(io_mtx);
                std::cerr << "String must include only numbers from 0 to 9 and less then 64 symbols\n";
            }
            continue;
        }

        // from my library(it sort and replace some exact symbols
        sort_and_replace(str);

        buffer.push(str);
        cv.notify_one();
    }
}

void thread2() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return !buffer.empty(); });

        std::string str = buffer.front();
        buffer.pop();

        {
            std::lock_guard<std::mutex> iolock(io_mtx);
            std::cout << "Processed line: " << str << std::endl;
        }

        size_t sum = sum_of_digits(str);
        std::string sum_str = std::to_string(sum);

        if (send(sockfd, sum_str.c_str(), sum_str.size(), 0) < 0) {
            {
                std::lock_guard<std::mutex> iolock(io_mtx);
                std::cerr << "Error.\n";
            }
            close(sockfd);
            connect_to_server();
        }
    }
}

int main() {
    connect_to_server();

    std::thread t1(thread1);
    std::thread t2(thread2);

    t1.join();
    t2.join();
    close(sockfd);
    return 0;
}

此代码无法正确将输出显示到控制台,即出现以下输出:

Error connecting to program2, retrying... 
Connected to server program2 
Enter line: 123 
Enter line: Processed line: 3KB1 
123 
Enter line: Processed line: 3KB1 
1234 
Enter line: Processed line: KB3KB1 
123 
Enter line: Processed line: 3KB1 
1234 
Enter line: Processed line: KB3KB1

我如何修复代码以使输出为:

Enter line: 1234
Processed line: KB3KB1
Enter line: 123
Processed line: 3KB1

我尝试使用lock_guard但它不起作用

c++ multithreading unix output
1个回答
0
投票

你有一场比赛,第一个线程写入

Enter line:
,然后第二个线程写入
Processed line: KB3KB1
,然后用户键入
1234

你需要保证下一个

Enter line:
会在
Processed line: KB3KB1
发生后发生,你可以使用
std::promise<void>
来实现这一点。

#include <thread>
#include <iostream>
#include <mutex>
#include <algorithm>
#include <queue>
#include <future>
#include <string>

std::mutex io_mtx;
std::mutex mtx;
std::condition_variable cv;
struct Message
{
    std::promise<void> promise;
    std::string message;
};

std::queue<Message> buffer;

void thread1() {
    std::string str;

    while (true) {
        {
            std::lock_guard<std::mutex> lock(io_mtx);
            std::cout << "Enter line: ";
        }

        std::getline(std::cin, str);

        std::unique_lock<std::mutex> lock(mtx);
        if (str == "exit") break;

        if (str.size() > 64 || !std::all_of(str.begin(), str.end(), ::isdigit)) {
            {
                std::lock_guard<std::mutex> iolock(io_mtx);
                std::cerr << "String must include only numbers from 0 to 9 and less then 64 symbols\n";
            }
            continue;
        }
        std::promise<void> promise;
        auto future = promise.get_future();
        buffer.push({ std::move(promise),str});
        lock.unlock();
        cv.notify_one();
        future.wait();
    }
}

void thread2() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return !buffer.empty(); });

        auto message = std::move(buffer.front());
        buffer.pop();

        {
            std::lock_guard<std::mutex> iolock(io_mtx);
            std::cout << "Processed line: " << message.message << std::endl;
        }

        message.promise.set_value();
       
    }
}

int main() {

    std::thread t1(thread1);
    std::thread t2(thread2);

    t1.join();
    t2.join();
    return 0;
}
Enter line: 12345
Processed line: 12345
Enter line: 12345
Processed line: 12345
Enter line:
© www.soinside.com 2019 - 2024. All rights reserved.