// Member Functions /////////////////////////////////////////////////// //Constructor public ObjectSafe(object used) { //Sanity check if (used == null) { return; } //Is the object castable as a threadedobject? IThreadedObject obj = used as IThreadedObject; if (obj != null) { //Yes! Let's handle it if (obj._eventLogger != null) { //Make sure it is necessary to log m_bLogActive = true; // !Log.isCurrent(obj.m_eventlogger); //Assume it if (m_bLogActive) { Log.assume(obj._eventLogger); } } //Enter the object's synchronous state DdMonitor.Enter(obj._sync); } else { Log.write(TLog.Warning, "Attempted to ObjectSafe a null/Non-Threaded object."); } m_used = used; }
// unloadSeries /// Unloads a series of handlers with the same guid /////////////////////////////////////////////////// public void unloadSeries(string guid) { //Be threadsafe using (DdMonitor.Lock(m_eventobject._sync)) { //Search through all our events foreach (KeyValuePair <string, HandlerList> kvp in this) { //For each handler List <CEventHandler> toRemove = new List <CEventHandler>(); foreach (CEventHandler eh in kvp.Value.methods) { //If the handler is in this series if (eh.guid == guid) { //Add it to the removal list toRemove.Add(eh); } } //Remove all condemned handlers foreach (CEventHandler eh in toRemove) { kvp.Value.methods.Remove(eh); } } } }
/// <summary>Exit the lock.</summary> public void Dispose() { if (_monitor != null) { DdMonitor.Exit(_monitor); _monitor = null; } }
protected void Dispose(bool disposeManagedResources) { //Do we have anything to dispose? if (!m_bDisposed) { //Is the object castable as a threadedobject? IThreadedObject obj = m_used as IThreadedObject; if (obj != null) { //Yes, let's clean up //Yield to the logging stack if it's active if (m_bLogActive && obj._eventLogger != null) { Log.yield(obj._eventLogger); } //Exit the synchronous state DdMonitor.Exit(obj._sync); } m_bDisposed = true; } }
/// <summary> /// Triggers an event /// </summary> static public void trigger(IEventObject obj, string name, bool bCautious, params object[] args) { //Attempt to hold the sync object bool bSync = true; if (bCautious) { bSync = DdMonitor.TryEnter(obj._sync); } else { DdMonitor.Enter(obj._sync); } //If this would block, queue the request in the threadpool if (!bSync) { //Queue! ThreadPool.QueueUserWorkItem( delegate(object state) { //Reattempt the trigger trigger(obj, name, false, args); } ); //Done return; } try { //Does the event exist? HandlerList list; if (!obj.events.TryGetValue(name, out list)) { //No? No need to worry return; } //Got it! Execute all handlers foreach (CEventHandler eh in list.methods) { //Sanity checks if (eh.argnum != args.Length) { throw new ArgumentException("Parameter mismatch while attempting to invoke custom event '" + name + "'"); } //Use the logger if necessary using (LogAssume.Assume(obj._eventLogger)) { //We're ok, time to invoke it //Custom handler? if (eh.customcaller == null) { eh.handler(eh.that, args); } else { //Allow them to call it eh.customcaller(eh, false, eh.that, args); } } } } catch (Exception ex) { //Log Log.write(TLog.Exception, "Exception occured while triggering event (" + name + "):\r\n" + ex.ToString()); } finally { DdMonitor.Exit(obj._sync); } }
/// <summary> /// Calls a singlecast event, returning a value /// </summary> static public object callsync(IEventObject obj, string name, bool bSync, params object[] args) { //Play safe? if (bSync) { using (DdMonitor.Lock(obj._sync)) { //Does the event exist? HandlerList list; if (!obj.events.TryGetValue(name, out list)) { //No? No need to worry return(null); } //Got it! Execute all handlers foreach (CEventHandler eh in list.methods) { //Sanity checks if (eh.argnum != args.Length) { throw new ArgumentException("Parameter mismatch while attempting to invoke custom event '" + name + "'"); } //We're ok, time to invoke it object ret = null; //Use the logger if necessary using (LogAssume.Assume(obj._eventLogger)) { //Custom handler? if (eh.customcaller == null) { ret = eh.handler(eh.that, args); } else { //Allow them to call it ret = eh.customcaller(eh, true, eh.that, args); } //Got our loot, return with it return(ret); } } return(null); } } else { //Does the event exist? HandlerList list; if (!obj.events.TryGetValue(name, out list)) { //No? No need to worry return(null); } //Got it! Execute all handlers foreach (CEventHandler eh in list.methods) { //Sanity checks if (eh.argnum != args.Length) { throw new ArgumentException("Parameter mismatch while attempting to invoke custom event '" + name + "'"); } //We're ok, time to invoke it object ret = null; //Use the logger if necessary using (LogAssume.Assume(obj._eventLogger)) { //Custom handler? if (eh.customcaller == null) { ret = eh.handler(eh.that, args); } else { //Allow them to call it ret = eh.customcaller(eh, true, eh.that, args); } //Got our loot, return with it return(ret); } } return(null); } }
internal static void write(TLog type, string Message, LogClient client, bool bCautious) { //Ignore fake clients if (client == null || client.m_bFake) { return; } //Attempt to hold the sync object bool bSync = true; if (bCautious) { bSync = DdMonitor.TryEnter(client); } else { DdMonitor.Enter(client); } //If this would block, queue the request in the threadpool if (!bSync) { //Queue! ThreadPool.QueueUserWorkItem( delegate(object state) { //Reattempt the assume write(type, Message, client, false); } ); //Done return; } //We need to release the sync object afterwards try { //Handle the message type string typechar = " "; switch (type) { case TLog.Inane: if (type >= m_consoleThreshold) { Console.ForegroundColor = ConsoleColor.DarkGray; } break; case TLog.Normal: if (type >= m_consoleThreshold) { Console.ForegroundColor = ConsoleColor.Gray; } break; case TLog.Warning: //Write to the warning log lock (m_warning) { m_warning.WriteLine("[" + DateTime.Now.ToLongTimeString() + "][" + client.m_clientname + client.m_clientnum + "] " + Message); m_warning.Flush(); } if (type >= m_consoleThreshold) { Console.ForegroundColor = ConsoleColor.Yellow; } typechar = "! "; break; case TLog.Error: //Write to the error log lock (m_error) { m_error.WriteLine("[" + DateTime.Now.ToLongTimeString() + "][" + client.m_clientname + client.m_clientnum + "] " + Message); m_error.Flush(); } if (type >= m_consoleThreshold) { Console.ForegroundColor = ConsoleColor.Red; } typechar = "* "; break; case TLog.Exception: //Write to the exception log lock (m_exception) { m_exception.WriteLine("[" + DateTime.Now.ToLongTimeString() + "][" + client.m_clientname + client.m_clientnum + "] " + Message); m_exception.Flush(); } if (type >= m_consoleThreshold) { Console.ForegroundColor = ConsoleColor.DarkRed; } typechar = "* "; break; } //Write the message to the logfile client.m_writer.WriteLine("[" + DateTime.Now.ToLongTimeString() + "]" + typechar + Message); client.m_writer.Flush(); //Obey the console threshold if (type >= m_consoleThreshold) { Console.WriteLine(Message); } } finally { DdMonitor.Exit(client); } //Sink the message into the logclient handlers client.sinkMessage(type, Message); //Sink it into our own handlers sinkMessage(type, client, Message); }
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); } }