Tôi đang làm việc với một số mã đa luồng cho một dự án trò chơi, và hơi mệt mỏi khi phân loại thông qua quá trình xuất dữ liệu được tạo bởi hai luồng bằng cách sử dụng cout để gỡ lỗi thư cùng một lúc. Tôi đã làm một số nghiên cứu và nhìn chằm chằm vào một bức tường trong một hoặc hai giờ trước khi đến với "cái gì đó". Đoạn mã sau sử dụng SFML để lưu giữ và phân luồng thời gian. Các mutex SFML chỉ được bao bọc các phần quan trọng trong cửa sổ.Chủ đề kỹ thuật an toàn cout. Tui bỏ lỡ điều gì vậy?
Tiêu đề:
#include <SFML\System.hpp>
#include <iostream>
class OutputStreamHack
{
public:
OutputStreamHack();
~OutputStreamHack();
ostream& outputHijack(ostream &os);
private:
sf::Clock myRunTime;
sf::Mutex myMutex;
};
static OutputStream OUTHACK;
ostream& operator<<(ostream& os, const OutputStreamHack& inputValue);
Thực hiện:
#include <SFML\System.hpp>
#include <iostream>
#include "OutputStreamHack.h"
using namespace std;
OutputStreamHack::OutputStreamHack()
{
myMutex.Unlock();
myRunTime.Reset();
}
OutputStreamHack::~OutputStreamHack()
{
myMutex.Unlock();
myRunTime.Reset();
}
ostream& OutputStreamHack::outputHijack(ostream &os)
{
sf::Lock lock(myMutex);
os<<"<"<<myRunTime.GetElapsedTime()<<","<<GetCurrentThreadId()<<"> "<<flush;
return os;
}
ostream& operator<<(ostream& os, const OutputStreamHack& inputValue)
{
OUTHACK.outputHijack(os);
return os;
}
Cách sử dụng:
cout<<OUTHACK<<val1<<val2<<val3....<<endl;
Ok, vì vậy cách làm việc này là thông qua một nhà điều hành chèn quá tải mà áp đặt chủ đề an toàn bằng cách khóa một iterator trong một đối tượng tĩnh, sau đó flushing buffer. Nếu tôi hiểu quy trình một cách chính xác (tôi chủ yếu là một lập trình viên tự dạy), cout xử lý các phần tử của chuỗi chèn của nó từ đầu đến cuối, chuyển một biến ostream xuống chuỗi cho mỗi phần tử được thêm vào luồng. Khi nó đạt đến phần tử OUTHACK, toán tử quá tải được gọi, mutex bị khóa và luồng được flushed.
Tôi đã thêm một số thông tin gỡ lỗi id thời gian/luồng vào đầu ra cho mục đích xác minh. Cho đến nay, thử nghiệm của tôi cho thấy rằng phương pháp này hoạt động. Tôi có một số chủ đề đập cout với nhiều đối số, và tất cả mọi thứ được sắp ra theo thứ tự đúng.
Từ những gì tôi đã đọc trong khi nghiên cứu vấn đề này, thiếu an toàn chủ đề trong cout dường như là một vấn đề khá phổ biến mà mọi người gặp phải trong khi mạo hiểm vào lập trình luồng. Những gì tôi đang cố gắng tìm ra là nếu kỹ thuật tôi đang sử dụng là một giải pháp đơn giản cho vấn đề, hoặc tôi nghĩ rằng tôi thông minh nhưng thiếu cái gì đó quan trọng.
Theo kinh nghiệm của tôi, từ thông minh khi được sử dụng để mô tả lập trình chỉ là một từ mã để giảm đau. Tôi đang ở một cái gì đó ở đây, hoặc chỉ cần đuổi theo những hacks tồi tệ xung quanh trong vòng tròn?
Cảm ơn!
Thực tế là nó hoạt động là may mắn. Chỉ có đầu ra của thời gian và id luồng được bảo vệ bởi mutex. Hoàn toàn có thể lấy một luồng khác lẻn vào giữa 'OUTHACK' và' val1'. –
Cân nhắc việc ghi vào 'ostringstream' trước, sau đó bán nội dung trong một thao tác thành' cout'. 'cout' nói chung sẽ là thread an toàn, nó chỉ là khóa rõ ràng cho mỗi cuộc gọi, và mỗi' << 'hoạt động là một cuộc gọi riêng biệt .... Bằng cách đó, không có khóa thêm trong mã ứng dụng của bạn - mà chỉ có thể giảm song song. –
Liên quan: [Là đồng bộ hóa/thread-safe?] (Http://stackoverflow.com/questions/6374264/is-cout-synchronized-thread-safe/6374525#6374525) – legends2k