Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:33

0001 //
0002 // JStreamLogBuffer.cc - implementation of the streambuf used by JStreamLog
0003 // Author: Craig Bookwalter
0004 // Date: Aug 2005
0005 //
0006 
0007 #include "JStreamLogBuffer.h"
0008 #include <stdio.h>
0009 #include <pthread.h>
0010 #include <sstream>
0011 using namespace std;
0012 
0013 pthread_mutex_t jstreamlog_mutex = PTHREAD_MUTEX_INITIALIZER;
0014 pthread_rwlock_t jstreamlog_rwlock = PTHREAD_RWLOCK_INITIALIZER;
0015 
0016 //------------------
0017 // JStreamLogBuffer
0018 //------------------
0019 JStreamLogBuffer::JStreamLogBuffer(std::streambuf* buf, const char* tag) :
0020 std::streambuf(),
0021 __sbuf(buf),
0022 __tag(strcpy(new char[strlen(tag)+1], tag)),
0023 //__newline(true),
0024 __prepend_timestamp(false),
0025 __prepend_threadstamp(false)
0026 {
0027     // The setp(0,0) call effectively sets the buffer size to 0
0028     // The reason we set it to 0 is so every character written
0029     // to the stream will invoke a call to the overflow() method below.
0030     setp(0,0);
0031 
0032     // The setg is for input so not really used here.
0033     setg(0,0,0);
0034 }
0035 
0036 //------------------
0037 // ~JStreamLogBuffer
0038 //------------------
0039 JStreamLogBuffer::~JStreamLogBuffer()
0040 {
0041     delete[] __tag;
0042 }
0043 
0044 //------------------
0045 // overflow
0046 //------------------
0047 int JStreamLogBuffer::overflow(int c)
0048 {
0049     // Because we called setp(0,0), this should get called for every character
0050     // written. Because multiple threads may be calling us, we want to sort
0051     // the characters into buffers, one for each thread. This way, we can prevent
0052     // 2 threads from writing messages "on top" of one another so that it comes
0053     // out as gibbersih.
0054     //
0055     // We use a rwlock here to hopefully minimize the perfomance hit we take for
0056     // locking/unlocking for every character written.
0057 
0058     pthread_rwlock_rdlock(&jstreamlog_rwlock);
0059     map<pthread_t,string>::iterator iter = thr_buffers.find(pthread_self());
0060     if(iter==thr_buffers.end()){
0061         // Add this thread to our list, creating a string for it
0062         pthread_rwlock_unlock(&jstreamlog_rwlock);  // release read only lock
0063         pthread_rwlock_wrlock(&jstreamlog_rwlock);  // obtain write lock
0064         thr_buffers[pthread_self()] = "";
0065         pthread_rwlock_unlock(&jstreamlog_rwlock);  // release write lock
0066         pthread_rwlock_rdlock(&jstreamlog_rwlock);  // re-obtain read only lock
0067     }
0068 
0069     // Get reference to this thread's string
0070     string &str = thr_buffers[pthread_self()];
0071 
0072     // Add this character to the string
0073     str += (char)c;
0074 
0075     // Check if "c" is a special value warranting a flush to __sbuf
0076     string copy_out;
0077     switch(c){
0078         case '\n':
0079         case '\r':
0080             copy_out = str;
0081             str.clear(); // reset the streamstring
0082             break;
0083         default:
0084             break;
0085      }
0086 
0087     // Release read lock
0088     pthread_rwlock_unlock(&jstreamlog_rwlock);
0089 
0090     // If we have a string to copy, then do it
0091     if(copy_out.size()!=0){
0092 
0093         // Prepend tag (if present)
0094         if(strlen(__tag)>0)copy_out.insert(0, string(__tag));
0095 
0096         // Optionally prepend threadid
0097         if(__prepend_threadstamp)copy_out.insert(0, getThreadStamp()+" # ");
0098 
0099         // Optionally prepend time
0100         if(__prepend_timestamp)copy_out.insert(0, getTimeStamp()+" # ");
0101 
0102         // Use the mutex to prevent more than one thread from writing at a time
0103         pthread_mutex_lock(&jstreamlog_mutex);
0104 
0105         const char *a = copy_out.c_str();
0106         for(unsigned int i=0; i<copy_out.size(); i++, a++)__sbuf->sputc(*a);
0107 
0108         pthread_mutex_unlock(&jstreamlog_mutex);
0109     }
0110 
0111     return 0;
0112 }
0113 
0114 //------------------
0115 // sync
0116 //------------------
0117 int JStreamLogBuffer::sync() {
0118     return static_cast<JStreamLogBuffer*>(__sbuf)->sync();
0119 }
0120 
0121 //------------------
0122 // getThreadStamp
0123 //------------------
0124 string JStreamLogBuffer::getThreadStamp() {
0125     stringstream ss;
0126     ss<<"thr="<<pthread_self();
0127     return ss.str();
0128 }
0129 
0130 //------------------
0131 // getTimeStamp
0132 //------------------
0133 string JStreamLogBuffer::getTimeStamp() {
0134     time_t thetime;
0135     time(&thetime);
0136     char* timestr = ctime(&thetime);
0137     int len = strlen(timestr);
0138     timestr[len-1] = '\0';
0139     return string(timestr);
0140 }
0141 
0142 //------------------
0143 // SetTag
0144 //------------------
0145 void JStreamLogBuffer::SetTag(string tag)
0146 {
0147     delete[] __tag;
0148     const char *ctag = tag.c_str();
0149     __tag = new char[strlen(ctag)+1];
0150     strcpy(__tag, ctag);
0151 }
0152