2016-04-12 46 views
-1

我有最糟糕的時間試圖做一個類,有一個std :: ofstream和一個std :: mutex被鎖定和解鎖以控制對ofstream的訪問。使用std :: mutex成員和運算符<<插入過載的線程安全訪問std :: ofstream成員?

基本上我想要一個類thread_safe_ofstreamwith一個< <運營商,所以我可以用它喜歡:

thread_safe_ofstream ofs; 

    ofs << "debug info from different threads" << std::endl; 

所以我知道我需要一個操作< <超載。雖然< < < < < < <右側的類有很多信息,但我無法找到任何有關如何實現自己的ostream類似輸入的文檔。

我知道下面的代碼不能工作,因爲無論輸入/輸出要求< <有,但這是我需要的類的精神。

Class thread_safe_ofstream 
{ 
    std::mutex mu; 
    std::ofstream stream; 
    template<typename T> 
    operator<<(T& thing) 
    { 
     mu.lock(); 
     stream << thing; 
     mu.unlock(); 
    } 
}; 

這樣一個thread_safe_ofstream可以< <「從多個線程d至沒有問題(我希望)。

+0

標準流必須是線程安全的。你必須更具體地說明你想用這把鎖完成什麼。 –

+0

@PeteBecker,可能是從單個輸出<<操作不應該交錯?這是一個有效的要求。 – SergeyA

+0

@SergeyA - 是的,當然可以猜測問題的目的是要問什麼。我正在尋找更明確的東西,這既不能也不能提供。 –

回答

0

這樣的事情?

template<typename T> 
thread_safe_ofstream& operator<<(const T& thing) 
{ 
    std::lock_guard<std::mutex> guard(mu); 
    stream << thing; 
    return *this; 
} 

然而,它通常是更好地執行operator <<作爲一個自由函數,而不是類成員。

+0

這似乎工作正常,但由於某些原因,它不能接受std :: endl? – OrangeSherbet

+0

「不能接受」是什麼意思? – SergeyA

+0

我可以'''任何const字符串,包括具有'\ n'字符的字符串,但是如果我把'stream << std :: endl'放到程序中。如果我嘗試'stream.flush()',它也會中止。花一些時間試圖找出原因。 – OrangeSherbet

0

你可以有這樣的實現方式,例如:

class thread_safe_ofstream 
{ 
    std::mutex mu; 
    std::ofstream stream; 

    template<typename T> 
    void put(const T& thing) { 
     std::lock_guard<std::mutex> lock(mu); 
     stream << thing; 
    } 

    friend template<typename T> 
    thread_safe_ofstream& operator<<(thread_safe_ofstream& tsof, const T& value) { 
     tsof.put(value); 
     return tsof; 
    } 
}; 
0

下面是一個完整的類,將打印從像ts_ofs << "print this message" << std::endl命令通常-ungarbled文本除了後續<<是另一個線程之間可以開始打印。我懷疑可以解決這個問題,但我不知道該怎麼做。靈感來自this post

struct ts_ofstream 
{ 
    std::ofstream ostream; 
    std::mutex mu; 

    //This is only for testing, you can initialize ostream however/wherever you like. 
    void init(bool test = false) 
    { 
     ostream = std::ofstream("C:/Users/Joey/Desktop/THREAD_DEBUG.txt", ios::out); 
     if (test) 
     { 
      ostream << "Testing stream "; 
      ostream << std::endl; 
      ostream << "Testing complete" << std::endl; 
     } 
    } 

    template <typename T> 
    friend ts_ofstream& operator<<(ts_ofstream& s, const T& x); 

    // function that takes a custom stream, and returns it 
    typedef ts_ofstream& (*MyStreamManipulator)(ts_ofstream&); 

    // take in a function with the custom signature 
    ts_ofstream& operator<<(MyStreamManipulator manip) 
    { 
     // call the function, and return it's value 
     return manip(*this); 
    } 

    // define the custom endl for this stream. 
    // note how it matches the `MyStreamManipulator` 
    // function signature 
    static ts_ofstream& endl(ts_ofstream& stream) 
    { 
     // print a new line 
     stream.ostream << std::endl; 

     return stream; 
    } 

    // this is the type of std::ofstream 
    typedef std::basic_ostream<char, std::char_traits<char> > CoutType; 

    // this is the function signature of std::endl 
    typedef CoutType& (*StandardEndLine)(CoutType&); 

    // define an operator<< to take in std::endl 
    ts_ofstream& operator<<(StandardEndLine manip) 
    { 
     // call the function, but we cannot return it's value 
     manip(this->ostream); 
     return *this; 
    } 
}; 

template<typename T> 
ts_ofstream & operator<<(ts_ofstream & s, const T & x) 
{ 
    std::lock_guard<std::mutex> lock(s.mu); 
    s.ostream << x; 
    return s; 
} 
相關問題