// getCurrent /// Gets the current log client from the top of the setack /////////////////////////////////////////////////// public static LogClient getCurrent() { //Enter lock m_threadlock.AcquireReaderLock(Timeout.Infinite); //Get the current logclient logstack clientstack = null; int threadid = Thread.CurrentThread.ManagedThreadId; try { //The list may be modified, so we want to remain in sync if (!m_threads.TryGetValue(threadid, out clientstack)) { //Failed to find anything related to the thread //Let's assume that the stack just hasn't been created return(null); } //Take a look if (clientstack.Count == 0) { return(null); } return(clientstack.Peek()); } finally { //Release again m_threadlock.ReleaseReaderLock(); } }
internal static void write(TLog type, string Message, Thread thread, bool bCautious) { //Get a reader lock m_threadlock.AcquireReaderLock(Timeout.Infinite); //We need to release the sync object afterwards LogClient client = null; try { //Get the current logclient logstack clientstack = null; int threadid = thread.ManagedThreadId; //The list may be modified, so we want to remain in sync if (!m_threads.TryGetValue(threadid, out clientstack)) { //Failed to find it; make a note lock (m_warning) { m_warning.WriteLine("[" + DateTime.Now.ToLongTimeString() + "][Log] Failed to find associated clientstack for thread. (write)"); m_warning.WriteLine("[" + DateTime.Now.ToLongTimeString() + "][Log] Message: " + Message); m_warning.Flush(); } return; } //If we don't have any logclients, don't bother if (clientstack.Count == 0) { //Notify them lock (m_warning) { m_warning.WriteLine("[" + DateTime.Now.ToLongTimeString() + "][Log] Attempted to write to log when no LogClients were active."); m_warning.Flush(); } return; } //Got it! client = clientstack.Peek(); } finally { //Release our lock m_threadlock.ReleaseReaderLock(); } //Redirect write(type, Message, client, bCautious); }
internal static void yield(LogClient client, Thread thread, bool bCautious, long sync) { //Validate the logclient if (client == null) { //Wtf? lock (m_error) { m_error.WriteLine("[" + DateTime.Now.ToLongTimeString() + "][Log] Attempted to yield null LogClient. (yield)"); m_error.Flush(); } return; } //Ignore fake clients if (client.m_bFake) { return; } //Enter the lock to access the threads list logstack clientstack = null; int threadid = thread.ManagedThreadId; m_threadlock.AcquireReaderLock(Timeout.Infinite); try { //Find our associated client stack if (!m_threads.TryGetValue(threadid, out clientstack)) { //Failed to find it; let's create a new one LockCookie lc = new LockCookie(); lc = m_threadlock.UpgradeToWriterLock(Timeout.Infinite); try { clientstack = new logstack(); //Add it to the list m_threads.Add(threadid, clientstack); } finally { m_threadlock.DowngradeFromWriterLock(ref lc); } } } finally { m_threadlock.ReleaseReaderLock(); } //Set our sync id if (sync == -1) { sync = Interlocked.Increment(ref clientstack.m_runningsync); } //Attempt to hold the sync object bool bSync = true; if (bCautious) { bSync = DdMonitor.TryEnter(clientstack); } else { DdMonitor.Enter(clientstack); } //If this would block, queue the request in the threadpool if (!bSync) { //Queue! ThreadPool.QueueUserWorkItem( delegate(object state) { //Reattempt the assume yield(client, thread, false, sync); } ); //Done return; } //We need to release the sync object afterwards try { //Wait on our sync if (!DdMonitor.bNoSync) { while (sync - 1 != Interlocked.Read(ref clientstack.m_actualsync)) { Monitor.Wait(clientstack); } } //Make sure the specified client holds the stack LogClient stackowner = clientstack.Peek(); if (stackowner.m_guid != client.m_guid) { //You can't yield if you don't own the stack //Report the error and do nothing lock (m_warning) { m_warning.WriteLine("[" + DateTime.Now.ToLongTimeString() + "][Log] Client attempted to yield in a thread whose logging context it didn't own."); m_warning.Flush(); } return; } //Remove the client from the stack clientstack.Pop(); //If the stack has nothing left.. if (clientstack.Count == 0) { //Remove it from the thread list m_threadlock.AcquireWriterLock(Timeout.Infinite); try { m_threads.Remove(threadid); } finally { m_threadlock.ReleaseWriterLock(); } } //Increase the count Interlocked.Exchange(ref clientstack.m_actualsync, sync); //Done if (!DdMonitor.bNoSync) { Monitor.Pulse(clientstack); } } finally { DdMonitor.Exit(clientstack); } }
internal static void assume(LogClient client, Thread thread, bool bCautious, long sync) { //Validate the logclient if (client == null) { //Wtf? lock (m_error) { m_error.WriteLine("[" + DateTime.Now.ToLongTimeString() + "][Log] Attempted to add null LogClient. (assume)"); m_error.Flush(); } return; } //Ignore fake clients if (client.m_bFake) { return; } //Enter the lock to access the threads list logstack clientstack = null; m_threadlock.AcquireReaderLock(Timeout.Infinite); try { //Find our associated client stack int threadid = thread.ManagedThreadId; //We're modifying the list, so we need to be synced if (!m_threads.TryGetValue(threadid, out clientstack)) { //Failed to find it; let's create a new one LockCookie lc = new LockCookie(); lc = m_threadlock.UpgradeToWriterLock(Timeout.Infinite); try { clientstack = new logstack(); //Add it to the list m_threads.Add(threadid, clientstack); } finally { m_threadlock.DowngradeFromWriterLock(ref lc); } } } finally { m_threadlock.ReleaseReaderLock(); } //Set our sync id if (sync == -1) { sync = Interlocked.Increment(ref clientstack.m_runningsync); } //Attempt to hold the sync object bool bSync = true; if (bCautious) { bSync = DdMonitor.TryEnter(clientstack); } else { DdMonitor.Enter(clientstack); } //If this would block, queue the request in the threadpool if (!bSync) { //Queue! ThreadPool.QueueUserWorkItem( delegate(object state) { //Reattempt the assume assume(client, thread, false, sync); } ); //Done return; } //We need to release the sync object afterwards try { //Wait on our sync if (!DdMonitor.bNoSync) { while (sync - 1 != Interlocked.Read(ref clientstack.m_actualsync)) { Monitor.Wait(clientstack); } } //Add our client clientstack.Push(client); //Increase the count Interlocked.Exchange(ref clientstack.m_actualsync, sync); //Done. if (!DdMonitor.bNoSync) { Monitor.Pulse(clientstack); } } finally { DdMonitor.Exit(clientstack); } }