2010-08-25 57 views
2

內終止我很新的這一點,並道歉,如果我的問題不明確。需要知道如何檢查,如果輸入的字符串已經在C++線程安全記錄

我已經創建了C++中的線程安全記錄。這個記錄器將用於大型程序&將從多個地方被調用。我正在使用單例,所以只有一個記錄器實例。該記錄器輸出到文件&到控制檯。它的行爲類似於cout;它從另一個文件中取得一個字符串,(如果需要連接它),將peices存儲在緩衝區中,直到字符串完成,然後使用cout輸出。該字符串被存儲爲一個const char *。現在,互斥鎖被鎖定在一個函數中,並在另一個函數中解鎖(這是我的問題),它會重載endl操作符。

我的問題是,如果用戶在記錄器被稱爲其他文件寫入ENDL此功能(當互斥被解鎖)纔有效。我需要這是一個多用途的實用程序,它不會依賴用戶編寫的內容,因爲用戶可能不會使用endl或可能經常使用它。我現在需要一些方法讓我的記錄器識別字符串(來自另一個文件)何時完成,以便它可以清空緩衝區。目前endl就像一個關鍵字&我需要一些手段,使其工作沒有任何關鍵詞。

我最初想我可以找到一些方法來檢查字符串中的「\ 0」終止符,然後使用支票知道該字符串完成,然後清空了緩衝區。然而,當我這樣做的時候,我會遇到越界的錯誤。

謝謝您的時間

+0

如果你放一點源代碼,比如如何調用記錄器,這將有所幫助。錯誤消息的一般格式是什麼,以及您使用的是什麼類型。從你的問題,它可以是std :: string,stream或字符數組。 – 2010-08-25 21:55:44

+0

記錄器被設計爲處理std :: string和const char *它同時處理 – joy 2010-08-26 18:06:32

回答

0

通常這是一個壞主意,有互斥鎖功能於一體,並在另一個解鎖。應該使用相同的功能鎖定和解鎖。

我創建類似的東西,通常我做了一個C++類調用錯誤。

這樣,用戶就創建了一個錯誤的對象,而錯誤的對象處理所有終止的東西。然後將錯誤對象發送到ErrorLogger隊列,並且當ErrorLogger隊列爲空時錯誤記錄器終止。那麼您不必擔心互斥鎖,因爲ErrorLogger有時間處理隊列。

+0

丹尼斯,對此,我會研究你提出的解決方案,看看它是否可以爲我工作。謝謝您的回覆。但是,我不知道我是否可以擺脫這些互斥體。這是一個非常複雜的記錄器,它具有許多我以上沒有提到的附加功能。但是他們需要在鎖定和解鎖之間完成。我在別處使用互斥鎖來確保記錄器是線程安全的並且具有這些功能。儘管如此,我仍然需要一些手段來了解字符串何時完成。我如何檢查一個字符串是否沒有關鍵字? – joy 2010-08-25 20:49:50

+0

我需要了解更多關於字符串的信息。它只是一個std :: string,字符數組或流? 我假設你使用互斥體,以防止另一個線程發佈當前的錯誤信息,而你寫一箇舊的文件正確? – 2010-08-25 21:37:19

+0

如果您從文件中讀取數據,您能跟蹤文件中每行的時間長度嗎? std :: string line; getline(inputFile,line); int lengthInCharacters = line.length() – 2010-08-25 21:48:16

4

我不太確定我得到的情況,但它聽起來像是你想有一個代理:

class LogSingleton 
{ 
public: 
    LogSingleton& instance() { /* ... */ } 

    void lock(); // lock mutex 
    void unlock(); // unlock mutex 

    template <typename T> 
    friend LogSingleton& operator<<(LogSingleton& pLog, const T& pX) 
    { 
     // needs to be locked first 
     assert(is_locked()); 

     /* output pX however */ 

     return pLog; 
    } 
}; 

class LogProxy 
{ 
public: 
    LogProxy() 
    { 
     // manage lock in proxy 
     LogSingleton::instance().lock();    
    } 

    ~LogProxy() 
    { 
     LogSingleton::instance().unlock();    
    } 
}; 

// forward input into the proxy to the log, knowing it's locked 
template <typename T> 
LogProxy& operator<<(LogProxy& pProxy, const T& pX) 
{ 
    LogSingleton::instance() << pX; 

    return pProxy; 
} 

// now expose proxy 
typedef LogProxy log; 

而且你應該這樣做:

log() << "its locked now" << "and the temporary will die" << "here ->"; 

鎖定在做構造函數和析構函數,並在最後調用析構函數。


正如Tony正確指出的那樣,這會持續不必要的鎖定。該鎖僅用於「最終」輸出到LogSingleton。想象一下:

log() << "this next function takes 5 minutes" 
     << my_utterly_crappy_function() << "ouch"; 

沒有記錄互斥鎖被鎖定了很長時間。更好的辦法是緩衝輸出,然後立即輸出:

class LogProxy 
{ 
public: 
    ~LogProxy() 
    { 
     // manage lock in proxy 
     LogSingleton::instance().lock(); 

     // no-throw, or wrap mutex use in a scoped-lock 
     LogSingleton::instance() << mBuffer.rdbuf(); 

     LogSingleton::instance().unlock();    
    } 

    // buffer output 
    template <typename T> 
    friend LogProxy& operator<<(LogProxy& pProxy, const T& pX) 
    { 
     mBuffer << pX; 

     return pProxy; 
    } 

private: 
    std::ostringstream mBuffer; 
}; 

現在,直到緩衝區準備好輸出,纔會獲取鎖。

+0

如果應用程序正在記錄大量數據,那麼此解決方案可能會嚴重影響性能。雖然對於輕量級日誌記錄或一個線程執行幾乎所有日誌記錄的效率較低,但它更容易將ostringstream中的輸出連接起來,只有在準備寫入時才能獲取單身的鎖定。 (在某些系統上,當流/文件保存它自己的互斥鎖時,將執行單個寫入()到流,這保證了原子性 - 但這不是可移植的)。 – 2010-08-26 08:33:04

+0

@Tony:好點。我會補充一點。 – GManNickG 2010-08-26 08:37:15

相關問題