protected void DeliverEventToList (object sender, EventArgs args, ListenerList list) { for (int i = 0; i < list.Count; i ++) { IWeakEventListener listener = list[i]; listener.ReceiveWeakEvent (GetType(), sender, args); } }
internal ListenerHandle(ListenerList parent, Type type, RepositoryListener listener ) { this.parent = parent; this.type = type; this.listener = listener; }
public override void InitializePlugin(IPoderosaWorld poderosa) { _instance = this; base.InitializePlugin(poderosa); _sessionMap = new TypedHashtable<ISession, SessionHost>(); _documentMap = new TypedHashtable<IPoderosaDocument, DocumentHost>(); _docViewRelationHandler = poderosa.PluginManager.CreateExtensionPoint("org.poderosa.core.sessions.docViewRelationHandler", typeof(IDocViewRelationEventHandler), this); _activeDocumentChangeListeners = new ListenerList<IActiveDocumentChangeListener>(); _activeDocumentChangeListeners.Add(new WindowCaptionManager()); _sessionListeners = new ListenerList<ISessionListener>(); }
protected void DeliverEventToList(object sender, EventArgs args, ListenerList list) { if (list == null) throw new ArgumentNullException("list"); for (int i = 0; i < list.Count; i++) { IWeakEventListener listener = list[i]; listener.ReceiveWeakEvent(GetType(), sender, args); } }
public override void InitializePlugin(IPoderosaWorld poderosa) { base.InitializePlugin(poderosa); _instance = this; _commands = new List<IGeneralCommand>(); _idToCommand = new TypedHashtable<string, IGeneralCommand>(); _keyBind = new KeyBindConfiguration(); _keyBindChangeListener = new ListenerList<IKeyBindChangeListener>(); BasicCommandImplementation.Build(); poderosa.PluginManager.FindExtensionPoint(PreferencePlugin.EXTENSIONPOINT_NAME).RegisterExtension(this); }
protected void DeliverEventToList(object sender, EventArgs args, ListenerList list) { if (list == null) { throw new ArgumentNullException("list"); } for (int i = 0; i < list.Count; i++) { IWeakEventListener listener = list[i]; listener.ReceiveWeakEvent(GetType(), sender, args); } }
/// <summary> /// If the given list is in use (which means an event is currently /// being delivered), replace it with a clone. The existing /// users will finish delivering the event to the original list, /// without interference from changes to the new list. /// </summary> /// <returns> /// True if the list was cloned. Callers will probably want to /// insert the new list in their own data structures. /// </returns> public static bool PrepareForWriting(ref ListenerList list) { bool inUse = list.BeginUse(); list.EndUse(); if (inUse) { list = list.Clone(); } return(inUse); }
public override void InitializePlugin(IPoderosaWorld poderosa) { base.InitializePlugin(poderosa); _instance = this; _commands = new List <IGeneralCommand>(); _idToCommand = new TypedHashtable <string, IGeneralCommand>(); _keyBind = new KeyBindConfiguration(); _keyBindChangeListener = new ListenerList <IKeyBindChangeListener>(); BasicCommandImplementation.Build(); poderosa.PluginManager.FindExtensionPoint(PreferencePlugin.EXTENSIONPOINT_NAME).RegisterExtension(this); }
private void AddListener(INotifyPropertyChanged source, string propertyName, IWeakEventListener listener, EventHandler <PropertyChangedEventArgs> handler) { using (WriteLock) { HybridDictionary dict = (HybridDictionary)this[source]; if (dict == null) { // no entry in the hashtable - add a new one dict = new HybridDictionary(true /* case insensitive */); this[source] = dict; // listen for the desired events StartListening(source); } ListenerList list = (ListenerList)dict[propertyName]; if (list == null) { // no entry in the dictionary - add a new one list = new ListenerList <PropertyChangedEventArgs>(); dict[propertyName] = list; } // make sure list is ready for writing if (ListenerList.PrepareForWriting(ref list)) { dict[propertyName] = list; } // add a listener to the list if (handler != null) { ListenerList <PropertyChangedEventArgs> hlist = (ListenerList <PropertyChangedEventArgs>)list; hlist.AddHandler(handler); } else { list.Add(listener); } dict.Remove(AllListenersKey); // invalidate list of all listeners _proposedAllListenersList = null; // schedule a cleanup pass ScheduleCleanup(); } }
private void RemoveListener(INotifyPropertyChanged source, string propertyName, IWeakEventListener listener, EventHandler <PropertyChangedEventArgs> handler) { using (WriteLock) { HybridDictionary dict = (HybridDictionary)this[source]; if (dict != null) { ListenerList list = (ListenerList)dict[propertyName]; if (list != null) { // make sure list is ready for writing if (ListenerList.PrepareForWriting(ref list)) { dict[propertyName] = list; } // remove a listener from the list if (handler != null) { ListenerList <PropertyChangedEventArgs> hlist = (ListenerList <PropertyChangedEventArgs>)list; hlist.RemoveHandler(handler); } else { list.Remove(listener); } // when the last listener goes away, remove the list if (list.IsEmpty) { dict.Remove(propertyName); } } if (dict.Count == 0) { StopListening(source); Remove(source); } dict.Remove(AllListenersKey); // invalidate list of all listeners _proposedAllListenersList = null; } } }
public void Add(Guid EventID, Del_HandleEvent EventHandler, enPriority HandlePriority) { //Case:Exist eventId matched ListenerGroup if (m_Listeners.TryGetValue(EventID, out var ListenerGroup)) { //Case: Exist priority matched Listener List //Act: Just Add Listener if (ListenerGroup.TryGetValue(HandlePriority, out var ListenerList)) { m_PrioritiesDic.Add(EventHandler, HandlePriority); ListenerList.Add(EventHandler); } //Case: no priority matched Listener List //Act: Make a instnace of Listener list first and Add Listener else { ListenerList = new List <Del_HandleEvent>(); m_PrioritiesDic.Add(EventHandler, HandlePriority); ListenerList.Add(EventHandler); ListenerGroup.Add(HandlePriority, ListenerList); } } //Case: no eventId matched ListenerGroup else { //Make an instance of ListenerGroup ListenerGroup = new SortedDictionary <enPriority, List <Del_HandleEvent> >(); //Make an instance of ListenerList List <Del_HandleEvent> ListenerList = new List <Del_HandleEvent>(); //Save to dictionary m_PrioritiesDic.Add(EventHandler, HandlePriority); //add Handler ListenerList.Add(EventHandler); //add ListenerList ListenerGroup.Add(HandlePriority, ListenerList); //add ListenerGroup m_Listeners.Add(EventID, ListenerGroup); } }
internal void Remove(IWeakEventListener listener) { if (listener == null) { return; } ListenerList.PrepareForWriting(ref _listeners); _listeners.Remove(listener); if (_listeners.IsEmpty) { StopListening(); } }
public TerminalSettings() { //IPoderosaCulture culture = TerminalEmulatorPlugin.Instance.PoderosaWorld.Culture; //if (culture.IsJapaneseOS || culture.IsSimplifiedChineseOS || culture.IsTraditionalChineseOS || culture.IsKoreanOS) // _encoding = EncodingType.UTF8; //else _encoding = EncodingType.ISO8859_1; _debug = 0; _terminalType = TerminalType.XTerm; _localecho = false; _lineFeedRule = LineFeedRule.Normal; _transmitnl = NewLine.CR; _multiLogSettings = new MultiLogSettings(); _listeners = new ListenerList <ITerminalSettingsChangeListener>(); }
public TerminalSettings() { IPoderosaCulture culture = TerminalEmulatorPlugin.Instance.PoderosaWorld.Culture; if (culture.IsJapaneseOS || culture.IsSimplifiedChineseOS || culture.IsTraditionalChineseOS || culture.IsKoreanOS) _encoding = EncodingType.UTF8; else _encoding = EncodingType.ISO8859_1; _terminalType = TerminalType.XTerm; _localecho = false; _lineFeedRule = LineFeedRule.Normal; _transmitnl = NewLine.CR; _renderProfile = null; _shellSchemeName = ShellSchemeCollection.DEFAULT_SCHEME_NAME; _enabledCharTriggerIntelliSense = false; _multiLogSettings = new MultiLogSettings(); _listeners = new ListenerList<ITerminalSettingsChangeListener>(); }
// add a listener public void Add(IWeakEventListener listener, EventHandler <ValueChangedEventArgs> handler) { // make sure list is ready for writing ListenerList list = _listeners; if (ListenerList.PrepareForWriting(ref list)) { _listeners = (ListenerList <ValueChangedEventArgs>)list; } if (handler != null) { _listeners.AddHandler(handler); } else { _listeners.Add(listener); } }
public void StoreAllListenersList(ListenerList <PropertyChangedEventArgs> list) { // test again, in case another thread changed _proposedAllListersList. if (_proposedAllListenersList == list) { _dict[AllListenersKey] = new PropertyRecord(AllListenersKey, this, list); _proposedAllListenersList = null; } // Another thread could have changed _proposedAllListersList // since we set it (earlier in this method), either // because it calculated a new one while handling a PropertyChanged(""), // or because it added/removed/purged a listener. // In that case, we will simply abandon our proposed list and we'll // have to compute it again the next time. But that only happens // if there's thread contention. It's not worth doing something // more complicated just for that case. }
/// <summary> /// Remove dead entries from the data for the given source. Returns true if /// some entries were actually removed. /// </summary> protected virtual bool Purge(object source, object data, bool purgeAll) { bool foundDirt = false; bool removeList = purgeAll || source == null; // remove dead entries from the list if (!removeList) { ListenerList list = (ListenerList)data; if (ListenerList.PrepareForWriting(ref list) && source != null) { Table[this, source] = list; } if (list.Purge()) { foundDirt = true; } removeList = list.IsEmpty; } // if the list is no longer needed, stop listening to the event if (removeList) { if (source != null) // source may have been GC'd { StopListening(source); // remove the list completely (in the purgeAll case, we'll do it later) if (!purgeAll) { Table.Remove(this, source); foundDirt = true; } } } return(foundDirt); }
public TerminalSettings() { //IPoderosaCulture culture = TerminalEmulatorPlugin.Instance.PoderosaWorld.Culture; //if (culture.IsJapaneseOS || culture.IsSimplifiedChineseOS || culture.IsTraditionalChineseOS || culture.IsKoreanOS) // _encoding = EncodingType.UTF8; //else // _encoding = EncodingType.ISO8859_1; _encoding = Poderosa.Protocols.CygwinUtil.CygwinDefaultEncoding; _terminalType = TerminalType.Cygwin; _localecho = false; _lineFeedRule = LineFeedRule.Normal; _transmitnl = NewLine.CR; _renderProfile = null; _shellSchemeName = ShellSchemeCollection.DEFAULT_SCHEME_NAME; _enabledCharTriggerIntelliSense = false; _multiLogSettings = new MultiLogSettings(); _listeners = new ListenerList <ITerminalSettingsChangeListener>(); }
private void AddListener(object source, IWeakEventListener listener, Delegate handler) { object sourceKey = (source != null) ? source : StaticSource; using (Table.WriteLock) { ListenerList list = (ListenerList)Table[this, sourceKey]; if (list == null) { // no entry in the table - add a new one list = NewListenerList(); Table[this, sourceKey] = list; // listen for the desired event StartListening(source); } // make sure list is ready for writing if (ListenerList.PrepareForWriting(ref list)) { Table[this, source] = list; } // add a target to the list of listeners if (handler != null) { list.AddHandler(handler); } else { list.Add(listener); } // schedule a cleanup pass (heuristic (b) described above) ScheduleCleanup(); } }
private static uint KeepListener( GLib.Signal.EmissionHook listener, string objType, string signalName, string hookData) { GLib.GType type = GLib.GType.FromName(objType); if (type != GLib.GType.Invalid) { lock (listenerListMutex) { ListenerInfo info = new ListenerInfo(); info.Id = (uint)ListenerList.Count + 1; info.SignalName = signalName; info.Type = type; info.HookId = GLib.Signal.AddEmissionHook(signalName, type, listener); ListenerList.Add(info.Id, info); return(info.Id); } } else { throw new NotSupportedException("Invalid object type " + objType); } }
protected void CopyTo(ListenerList newList) { IWeakEventListener iwel; for (int k = 0, n = Count; k < n; ++k) { Listener listener = GetListener(k); if (listener.Target != null) { if (listener.HasHandler) { Delegate handler = listener.Handler; if (handler != null) { newList.AddHandler(handler); } } else if ((iwel = listener.Target as IWeakEventListener) != null) { newList.Add(iwel); } } } }
private void RemoveListener(object source, object target, Delegate handler) { object sourceKey = (source != null) ? source : StaticSource; using (Table.WriteLock) { ListenerList list = (ListenerList)Table[this, sourceKey]; if (list != null) { // make sure list is ready for writing if (ListenerList.PrepareForWriting(ref list)) { Table[this, sourceKey] = list; } // remove the target from the list of listeners if (handler != null) { list.RemoveHandler(handler); } else { list.Remove((IWeakEventListener)target); } // after removing the last listener, stop listening if (list.IsEmpty) { Table.Remove(this, sourceKey); StopListening(source); } } } }
/// <summary>Prevents a default instance of the WeakCultureChangedEventManager class from being created.</summary> WeakCultureChangedEventManager() { // creates a new list and assign it to listeners this.listeners = new ListenerList(); }
/// <summary> /// Return a copy of the list. /// </summary> public virtual ListenerList Clone() { ListenerList result = new ListenerList(); CopyTo(result); return result; }
/// <summary> /// Remove dead entries from the data for the given source. Returns true if /// some entries were actually removed. /// </summary> protected override bool Purge(object source, object data, bool purgeAll) { bool foundDirt = false; if (!purgeAll) { HybridDictionary dict = (HybridDictionary)data; int ignoredKeys = 0; if (!BaseAppContextSwitches.EnableWeakEventMemoryImprovements) { // copy the keys into a separate array, so that later on // we can change the dictionary while iterating over the keys ICollection ic = dict.Keys; String[] keys = new String[ic.Count]; ic.CopyTo(keys, 0); for (int i = keys.Length - 1; i >= 0; --i) { if (keys[i] == AllListenersKey) { ++ignoredKeys; continue; // ignore the special entry for now } // for each key, remove dead entries in its list bool removeList = purgeAll || source == null; if (!removeList) { ListenerList list = (ListenerList)dict[keys[i]]; if (ListenerList.PrepareForWriting(ref list)) { dict[keys[i]] = list; } if (list.Purge()) { foundDirt = true; } removeList = (list.IsEmpty); } // if there are no more entries, remove the key if (removeList) { dict.Remove(keys[i]); } } #if WeakEventTelemetry LogAllocation(ic.GetType(), 1, 12); // dict.Keys - Hashtable+KeyCollection LogAllocation(typeof(String[]), 1, 12 + ic.Count * 4); // keys #endif } else { Debug.Assert(_toRemove.Count == 0, "to-remove list should be empty"); // enumerate the dictionary using IDE explicitly rather than // foreach, to avoid allocating temporary DictionaryEntry objects IDictionaryEnumerator ide = dict.GetEnumerator() as IDictionaryEnumerator; while (ide.MoveNext()) { String key = (String)ide.Key; if (key == AllListenersKey) { ++ignoredKeys; continue; // ignore the special entry for now } // for each key, remove dead entries in its list bool removeList = purgeAll || source == null; if (!removeList) { ListenerList list = (ListenerList)ide.Value; if (ListenerList.PrepareForWriting(ref list)) { dict[key] = list; } if (list.Purge()) { foundDirt = true; } removeList = (list.IsEmpty); } // if there are no more entries, remove the key if (removeList) { _toRemove.Add(key); } } // do the actual removal (outside the dictionary iteration) if (_toRemove.Count > 0) { foreach (String key in _toRemove) { dict.Remove(key); } _toRemove.Clear(); _toRemove.TrimExcess(); } #if WeakEventTelemetry Type enumeratorType = ide.GetType(); if (enumeratorType.Name.IndexOf("NodeEnumerator") >= 0) { LogAllocation(enumeratorType, 1, 24); // ListDictionary+NodeEnumerator } else { LogAllocation(enumeratorType, 1, 36); // Hashtable+HashtableEnumerator } #endif } if (dict.Count == ignoredKeys) { // if there are no more listeners at all, remove the entry from // the main table, and prepare to stop listening purgeAll = true; if (source != null) // source may have been GC'd { this.Remove(source); } } else if (foundDirt) { // if any entries were purged, invalidate the special entry dict.Remove(AllListenersKey); _proposedAllListenersList = null; } } if (purgeAll) { // stop listening. List cleanup is handled by Purge() if (source != null) // source may have been GC'd { StopListening(source); } foundDirt = true; } return(foundDirt); }
public PropertyRecord(string propertyName, TypeRecord owner, ListenerList<PropertyChangedEventArgs> list) { _propertyName = propertyName; _typeRecord = owner; _list = list; }
public void StoreAllListenersList(ListenerList<PropertyChangedEventArgs> list) { // test again, in case another thread changed _proposedAllListersList. if (_proposedAllListenersList == list) { _dict[AllListenersKey] = new PropertyRecord(AllListenersKey, this, list); _proposedAllListenersList = null; } // Another thread could have changed _proposedAllListersList // since we set it (earlier in this method), either // because it calculated a new one while handling a PropertyChanged(""), // or because it added/removed/purged a listener. // In that case, we will simply abandon our proposed list and we'll // have to compute it again the next time. But that only happens // if there's thread contention. It's not worth doing something // more complicated just for that case. }
public ListenerList GetListenerList(string propertyName) { ListenerList list; if (!String.IsNullOrEmpty(propertyName)) { // source has changed a particular property. Notify targets // who are listening either for this property or for all properties. PropertyRecord pr = (PropertyRecord)_dict[propertyName]; ListenerList<PropertyChangedEventArgs> listeners = (pr == null) ? null : pr.List; PropertyRecord genericRecord = (PropertyRecord)_dict[String.Empty]; ListenerList<PropertyChangedEventArgs> genericListeners = (genericRecord == null) ? null : genericRecord.List; if (genericListeners == null) { if (listeners != null) { list = listeners; // only specific listeners } else { list = ListenerList.Empty; // no listeners at all } } else { if (listeners != null) { // there are both specific and generic listeners - // combine the two lists. list = new ListenerList<PropertyChangedEventArgs>(listeners.Count + genericListeners.Count); for (int i=0, n=listeners.Count; i<n; ++i) list.Add(listeners[i]); for (int i=0, n=genericListeners.Count; i<n; ++i) list.Add(genericListeners[i]); } else { list = genericListeners; // only generic listeners } } } else { // source has changed all properties. Notify all targets. // Use previously calculated combined list, if available. PropertyRecord pr = (PropertyRecord)_dict[AllListenersKey]; ListenerList<PropertyChangedEventArgs> pcList = (pr == null) ? null : pr.List; if (pcList == null) { // make one pass to compute the size of the combined list. // This avoids expensive reallocations. int size = 0; foreach (DictionaryEntry de in _dict) { Debug.Assert((String)de.Key != AllListenersKey, "special key should not appear"); size += ((PropertyRecord)de.Value).List.Count; } // create the combined list pcList = new ListenerList<PropertyChangedEventArgs>(size); // fill in the combined list foreach (DictionaryEntry de in _dict) { ListenerList listeners = ((PropertyRecord)de.Value).List; for (int i=0, n=listeners.Count; i<n; ++i) { pcList.Add(listeners.GetListener(i)); } } // save the result for future use (see below) _proposedAllListenersList = pcList; } list = pcList; } return list; }
public PropertyRecord(string propertyName, TypeRecord owner, ListenerList <PropertyChangedEventArgs> list) { _propertyName = propertyName; _typeRecord = owner; _list = list; }
/// <summary> /// Remove dead entries from the data for the given source. Returns true if /// some entries were actually removed. /// </summary> protected override bool Purge(object source, object data, bool purgeAll) { bool foundDirt = false; if (!purgeAll) { HybridDictionary dict = (HybridDictionary)data; int ignoredKeys = 0; if (!BaseAppContextSwitches.EnableWeakEventMemoryImprovements) { // copy the keys into a separate array, so that later on // we can change the dictionary while iterating over the keys ICollection ic = dict.Keys; String[] keys = new String[ic.Count]; ic.CopyTo(keys, 0); for (int i = keys.Length - 1; i >= 0; --i) { if (keys[i] == AllListenersKey) { ++ignoredKeys; continue; // ignore the special entry for now } // for each key, remove dead entries in its list bool removeList = purgeAll || source == null; if (!removeList) { ListenerList list = (ListenerList)dict[keys[i]]; if (ListenerList.PrepareForWriting(ref list)) { dict[keys[i]] = list; } if (list.Purge()) { foundDirt = true; } removeList = (list.IsEmpty); } // if there are no more entries, remove the key if (removeList) { dict.Remove(keys[i]); } } #if WeakEventTelemetry LogAllocation(ic.GetType(), 1, 12); // dict.Keys - Hashtable+KeyCollection LogAllocation(typeof(String[]), 1, 12 + ic.Count * 4); // keys #endif } else { Debug.Assert(_toRemove.Count == 0, "to-remove list should be empty"); // If an "in-use" list is changed, we will re-install its clone // back into the dictionary. Doing this inside the loop // causes an exception "collection was modified after the enumerator // was instantiated" (DDVSO 812614), so instead just record // what to do and do the actual work after the loop. // This is a rare case - it only arises if a PropertyChanged event // handler calls (indirectly) into the cleanup code - so allocate // the temporary memory lazily on the stack. // [In the bug, the indirect call comes about because the app's // event handler calls ShowDialog(), which pushes a dispatcher // frame to run a nested message pump. Then a pending cleanup task // reaches the front of the dispatcher queue before the dialog // is dismissed, effectively calling this method while the // PropertyChanged event delivery is in progress.] HybridDictionary toInstall = null; // enumerate the dictionary using IDE explicitly rather than // foreach, to avoid allocating temporary DictionaryEntry objects IDictionaryEnumerator ide = dict.GetEnumerator() as IDictionaryEnumerator; while (ide.MoveNext()) { String key = (String)ide.Key; if (key == AllListenersKey) { ++ignoredKeys; continue; // ignore the special entry for now } // for each key, remove dead entries in its list bool removeList = purgeAll || source == null; if (!removeList) { ListenerList list = (ListenerList)ide.Value; bool inUse = ListenerList.PrepareForWriting(ref list); bool isChanged = false; if (list.Purge()) { isChanged = true; foundDirt = true; } removeList = (list.IsEmpty); // if a cloned list changed, remember the details // so that the clone can be installed back into the // dictionary outside the iteration (DDVSO 812614) if (!removeList && inUse && isChanged) { if (toInstall == null) { // lazy allocation toInstall = new HybridDictionary(); } toInstall[key] = list; } } // if there are no more entries, remove the key if (removeList) { _toRemove.Add(key); } } // do the actual removal (outside the dictionary iteration) if (_toRemove.Count > 0) { foreach (String key in _toRemove) { dict.Remove(key); } _toRemove.Clear(); _toRemove.TrimExcess(); } // do the actual re-install of "in-use" lists that changed if (toInstall != null) { IDictionaryEnumerator installDE = toInstall.GetEnumerator() as IDictionaryEnumerator; while (installDE.MoveNext()) { String key = (String)installDE.Key; ListenerList list = (ListenerList)installDE.Value; dict[key] = list; } } #if WeakEventTelemetry Type enumeratorType = ide.GetType(); if (enumeratorType.Name.IndexOf("NodeEnumerator") >= 0) { LogAllocation(enumeratorType, 1, 24); // ListDictionary+NodeEnumerator } else { LogAllocation(enumeratorType, 1, 36); // Hashtable+HashtableEnumerator } #endif } if (dict.Count == ignoredKeys) { // if there are no more listeners at all, remove the entry from // the main table, and prepare to stop listening purgeAll = true; if (source != null) // source may have been GC'd { this.Remove(source); } } else if (foundDirt) { // if any entries were purged, invalidate the special entry dict.Remove(AllListenersKey); _proposedAllListenersList = null; } } if (purgeAll) { // stop listening. List cleanup is handled by Purge() if (source != null) // source may have been GC'd { StopListening(source); } foundDirt = true; } return(foundDirt); }
/// <summary> /// Remove dead entries from the data for the given source. Returns true if /// some entries were actually removed. /// </summary> protected override bool Purge(object source, object data, bool purgeAll) { bool foundDirt = false; if (!purgeAll) { HybridDictionary dict = (HybridDictionary)data; // copy the keys into a separate array, so that later on // we can change the dictionary while iterating over the keys ICollection ic = dict.Keys; String[] keys = new String[ic.Count]; ic.CopyTo(keys, 0); for (int i = keys.Length - 1; i >= 0; --i) { if (keys[i] == AllListenersKey) { continue; // ignore the special entry for now } // for each key, remove dead entries in its list bool removeList = purgeAll || source == null; if (!removeList) { ListenerList list = (ListenerList)dict[keys[i]]; if (ListenerList.PrepareForWriting(ref list)) { dict[keys[i]] = list; } if (list.Purge()) { foundDirt = true; } removeList = (list.IsEmpty); } // if there are no more entries, remove the key if (removeList) { dict.Remove(keys[i]); } } if (dict.Count == 0) { // if there are no more listeners at all, remove the entry from // the main table, and prepare to stop listening purgeAll = true; if (source != null) // source may have been GC'd { this.Remove(source); } } else if (foundDirt) { // if any entries were purged, invalidate the special entry dict.Remove(AllListenersKey); _proposedAllListenersList = null; } } if (purgeAll) { // stop listening. List cleanup is handled by Purge() if (source != null) // source may have been GC'd { StopListening(source); } foundDirt = true; } return(foundDirt); }
internal void Add(IWeakEventListener listener) { ListenerList.PrepareForWriting(ref _listeners); _listeners.Add(listener); }
internal bool Purge() { ListenerList.PrepareForWriting(ref _listeners); return(_listeners.Purge()); }
private void AddListener(INotifyPropertyChanged source, string propertyName, IWeakEventListener listener, EventHandler<PropertyChangedEventArgs> handler) { using (WriteLock) { HybridDictionary dict = (HybridDictionary)this[source]; if (dict == null) { // no entry in the hashtable - add a new one dict = new HybridDictionary(true /* case insensitive */); this[source] = dict; // listen for the desired events StartListening(source); } ListenerList list = (ListenerList)dict[propertyName]; if (list == null) { // no entry in the dictionary - add a new one list = new ListenerList<PropertyChangedEventArgs>(); dict[propertyName] = list; } // make sure list is ready for writing if (ListenerList.PrepareForWriting(ref list)) { dict[propertyName] = list; } // add a listener to the list if (handler != null) { ListenerList<PropertyChangedEventArgs> hlist = (ListenerList<PropertyChangedEventArgs>)list; hlist.AddHandler(handler); } else { list.Add(listener); } dict.Remove(AllListenersKey); // invalidate list of all listeners _proposedAllListenersList = null; // schedule a cleanup pass ScheduleCleanup(); } }
public ListenerList GetListenerList(string propertyName) { ListenerList list; if (!String.IsNullOrEmpty(propertyName)) { // source has changed a particular property. Notify targets // who are listening either for this property or for all properties. PropertyRecord pr = (PropertyRecord)_dict[propertyName]; ListenerList <PropertyChangedEventArgs> listeners = (pr == null) ? null : pr.List; PropertyRecord genericRecord = (PropertyRecord)_dict[String.Empty]; ListenerList <PropertyChangedEventArgs> genericListeners = (genericRecord == null) ? null : genericRecord.List; if (genericListeners == null) { if (listeners != null) { list = listeners; // only specific listeners } else { list = ListenerList.Empty; // no listeners at all } } else { if (listeners != null) { // there are both specific and generic listeners - // combine the two lists. list = new ListenerList <PropertyChangedEventArgs>(listeners.Count + genericListeners.Count); for (int i = 0, n = listeners.Count; i < n; ++i) { list.Add(listeners[i]); } for (int i = 0, n = genericListeners.Count; i < n; ++i) { list.Add(genericListeners[i]); } } else { list = genericListeners; // only generic listeners } } } else { // source has changed all properties. Notify all targets. // Use previously calculated combined list, if available. PropertyRecord pr = (PropertyRecord)_dict[AllListenersKey]; ListenerList <PropertyChangedEventArgs> pcList = (pr == null) ? null : pr.List; if (pcList == null) { // make one pass to compute the size of the combined list. // This avoids expensive reallocations. int size = 0; foreach (DictionaryEntry de in _dict) { Debug.Assert((String)de.Key != AllListenersKey, "special key should not appear"); size += ((PropertyRecord)de.Value).List.Count; } // create the combined list pcList = new ListenerList <PropertyChangedEventArgs>(size); // fill in the combined list foreach (DictionaryEntry de in _dict) { ListenerList listeners = ((PropertyRecord)de.Value).List; for (int i = 0, n = listeners.Count; i < n; ++i) { pcList.Add(listeners.GetListener(i)); } } // save the result for future use (see below) _proposedAllListenersList = pcList; } list = pcList; } return(list); }
/// <summary> /// If the given list is in use (which means an event is currently /// being delivered), replace it with a clone. The existing /// users will finish delivering the event to the original list, /// without interference from changes to the new list. /// </summary> /// <returns> /// True if the list was cloned. Callers will probably want to /// insert the new list in their own data structures. /// </returns> public static bool PrepareForWriting(ref ListenerList list) { bool inUse = list.BeginUse(); list.EndUse(); if (inUse) { list = list.Clone(); } return inUse; }
/// <summary> /// Deliver an event to the listeners on the given list /// </summary> protected void DeliverEventToList(object sender, EventArgs args, ListenerList list) { bool foundStaleEntries = false; Type managerType = this.GetType(); // deliver the event for (int k=0, n=list.Count; k<n; ++k) { IWeakEventListener listener = list[k]; if (listener != null) { bool handled = listener.ReceiveWeakEvent(managerType, sender, args); // if the event isn't handled, something is seriously wrong. This // means a listener registered to receive the event, but refused to // handle it when it was delivered. Such a listener is coded incorrectly. if (!handled) { Invariant.Assert(handled, SR.Get(SRID.ListenerDidNotHandleEvent), SR.Get(SRID.ListenerDidNotHandleEventDetail, listener.GetType(), managerType)); } } else { foundStaleEntries = true; } } // if we found stale entries, schedule a cleanup (heuristic b) if (foundStaleEntries) { ScheduleCleanup(); } }
protected void CopyTo(ListenerList newList) { IWeakEventListener iwel; for (int k=0, n=Count; k<n; ++k) { Listener listener = GetListener(k); if (listener.Target != null) { if (listener.HasHandler) { Delegate handler = listener.Handler; if (handler != null) { newList.AddHandler(handler); } } else if ((iwel = listener.Target as IWeakEventListener) != null) { newList.Add(iwel); } } } }
// event handler for PropertyChanged event private void OnPropertyChanged(object sender, PropertyChangedEventArgs args) { ListenerList list; string propertyName = args.PropertyName; // get the list of listeners using (ReadLock) { // look up the list of listeners HybridDictionary dict = (HybridDictionary)this[sender]; if (dict == null) { // this can happen when the last listener stops listening, but the // source raises the event on another thread after the dictionary // has been removed (bug 1235351) list = ListenerList.Empty; } else if (!String.IsNullOrEmpty(propertyName)) { // source has changed a particular property. Notify targets // who are listening either for this property or for all properties. ListenerList <PropertyChangedEventArgs> listeners = (ListenerList <PropertyChangedEventArgs>)dict[propertyName]; ListenerList <PropertyChangedEventArgs> genericListeners = (ListenerList <PropertyChangedEventArgs>)dict[String.Empty]; if (genericListeners == null) { if (listeners != null) { list = listeners; // only specific listeners } else { list = ListenerList.Empty; // no listeners at all } } else { if (listeners != null) { // there are both specific and generic listeners - // combine the two lists. list = new ListenerList <PropertyChangedEventArgs>(listeners.Count + genericListeners.Count); for (int i = 0, n = listeners.Count; i < n; ++i) { list.Add(listeners.GetListener(i)); } for (int i = 0, n = genericListeners.Count; i < n; ++i) { list.Add(genericListeners.GetListener(i)); } } else { list = genericListeners; // only generic listeners } } } else { // source has changed all properties. Notify all targets. // Use previously calculated combined list, if available. list = (ListenerList)dict[AllListenersKey]; if (list == null) { // make one pass to compute the size of the combined list. // This avoids expensive reallocations. int size = 0; foreach (DictionaryEntry de in dict) { Debug.Assert((String)de.Key != AllListenersKey, "special key should not appear"); size += ((ListenerList)de.Value).Count; } // create the combined list list = new ListenerList <PropertyChangedEventArgs>(size); // fill in the combined list foreach (DictionaryEntry de in dict) { ListenerList listeners = ((ListenerList)de.Value); for (int i = 0, n = listeners.Count; i < n; ++i) { list.Add(listeners.GetListener(i)); } } // save the result for future use (see below) _proposedAllListenersList = list; } } // mark the list "in use", even outside the read lock, // so that any writers will know not to modify it (they'll // modify a clone intead). list.BeginUse(); } // deliver the event, being sure to undo the effect of BeginUse(). try { DeliverEventToList(sender, args, list); } finally { list.EndUse(); } // if we calculated an AllListeners list, we should now try to store // it in the dictionary so it can be used in the future. This must be // done under a WriteLock - which is why we didn't do it immediately. if (_proposedAllListenersList == list) { using (WriteLock) { // test again, in case another thread changed _proposedAllListersList. if (_proposedAllListenersList == list) { HybridDictionary dict = (HybridDictionary)this[sender]; if (dict != null) { dict[AllListenersKey] = list; } _proposedAllListenersList = null; } // Another thread could have changed _proposedAllListersList // since we set it (earlier in this method), either // because it calculated a new one while handling a PropertyChanged(""), // or because it added/removed/purged a listener. // In that case, we will simply abandon our proposed list and we'll // have to compute it again the next time. But that only happens // if there's thread contention. It's not worth doing something // more complicated just for that case. } } }
/// <summary> /// Add a listener to the given source for the event. /// </summary> protected void ProtectedAddListener(object source, IWeakEventListener listener) { Debug.Assert(listener != null, "Listener cannot be null"); object sourceKey = (source != null) ? source : StaticSource; using (Table.WriteLock) { ListenerList list = (ListenerList)Table[this, sourceKey]; if (list == null) { // no entry in the table - add a new one list = new ListenerList(); Table[this, sourceKey] = list; // listen for the desired event StartListening(source); } // make sure list is ready for writing if (ListenerList.PrepareForWriting(ref list)) { Table[this, source] = list; } // add a target to the list of listeners list.Add(listener); // schedule a cleanup pass (heuristic (b) described above) ScheduleCleanup(); } }
/// <summary> /// Prevents a default instance of the <see cref="WeakOddsFormatChangedEventManager"/> class from being created. /// Creates a new instance of WeakOddsFormatChangedEventManager /// </summary> private WeakOddsFormatChangedEventManager() { // creates a new list and assign it to listeners this.listeners = new ListenerList(); }
/// <summary> /// Deliver an event to the listeners on the given list /// </summary> protected void DeliverEventToList(object sender, EventArgs args, ListenerList list) { bool foundStaleEntries = list.DeliverEvent(sender, args, this.GetType()); // if we found stale entries, schedule a cleanup (heuristic b) if (foundStaleEntries) { ScheduleCleanup(); } }
/// <summary> /// Prevents a default instance of the <see cref="WeakCultureChangedEventManager"/> class from being created. /// Creates a new instance of WeakCultureChangedEventManager /// </summary> private WeakCultureChangedEventManager() { // creates a new list and assign it to listeners listeners = new ListenerList(); }
// // Private Methods // // PropertyChanged is a special case - we superimpose per-property granularity // on top of this event, by keeping separate lists of listeners for // each property. // Add a listener to the named property (empty means "any property") private void PrivateAddListener(INotifyPropertyChanged source, IWeakEventListener listener, string propertyName) { Debug.Assert(listener != null && source != null && propertyName != null, "Listener, source, and propertyName of event cannot be null"); using (WriteLock) { HybridDictionary dict = (HybridDictionary)this[source]; if (dict == null) { // no entry in the hashtable - add a new one dict = new HybridDictionary(true /* case insensitive */); this[source] = dict; // listen for the desired events StartListening(source); } ListenerList list = (ListenerList)dict[propertyName]; if (list == null) { // no entry in the dictionary - add a new one list = new ListenerList(); dict[propertyName] = list; } // make sure list is ready for writing if (ListenerList.PrepareForWriting(ref list)) { dict[propertyName] = list; } // add a listener to the list list.Add(listener); dict.Remove(AllListenersKey); // invalidate list of all listeners _proposedAllListenersList = null; // schedule a cleanup pass ScheduleCleanup(); } }
// event handler for PropertyChanged event private void OnPropertyChanged(object sender, PropertyChangedEventArgs args) { ListenerList list; string propertyName = args.PropertyName; // get the list of listeners using (ReadLock) { // look up the list of listeners HybridDictionary dict = (HybridDictionary)this[sender]; if (dict == null) { // this can happen when the last listener stops listening, but the // source raises the event on another thread after the dictionary // has been removed (bug 1235351) list = ListenerList.Empty; } else if (!String.IsNullOrEmpty(propertyName)) { // source has changed a particular property. Notify targets // who are listening either for this property or for all properties. ListenerList<PropertyChangedEventArgs> listeners = (ListenerList<PropertyChangedEventArgs>)dict[propertyName]; ListenerList<PropertyChangedEventArgs> genericListeners = (ListenerList<PropertyChangedEventArgs>)dict[String.Empty]; if (genericListeners == null) { if (listeners != null) { list = listeners; // only specific listeners } else { list = ListenerList.Empty; // no listeners at all } } else { if (listeners != null) { // there are both specific and generic listeners - // combine the two lists. list = new ListenerList<PropertyChangedEventArgs>(listeners.Count + genericListeners.Count); for (int i=0, n=listeners.Count; i<n; ++i) list.Add(listeners.GetListener(i)); for (int i=0, n=genericListeners.Count; i<n; ++i) list.Add(genericListeners.GetListener(i)); } else { list = genericListeners; // only generic listeners } } } else { // source has changed all properties. Notify all targets. // Use previously calculated combined list, if available. list = (ListenerList)dict[AllListenersKey]; if (list == null) { // make one pass to compute the size of the combined list. // This avoids expensive reallocations. int size = 0; foreach (DictionaryEntry de in dict) { Debug.Assert((String)de.Key != AllListenersKey, "special key should not appear"); size += ((ListenerList)de.Value).Count; } // create the combined list list = new ListenerList<PropertyChangedEventArgs>(size); // fill in the combined list foreach (DictionaryEntry de in dict) { ListenerList listeners = ((ListenerList)de.Value); for (int i=0, n=listeners.Count; i<n; ++i) { list.Add(listeners.GetListener(i)); } } // save the result for future use (see below) _proposedAllListenersList = list; } } // mark the list "in use", even outside the read lock, // so that any writers will know not to modify it (they'll // modify a clone intead). list.BeginUse(); } // deliver the event, being sure to undo the effect of BeginUse(). try { DeliverEventToList(sender, args, list); } finally { list.EndUse(); } // if we calculated an AllListeners list, we should now try to store // it in the dictionary so it can be used in the future. This must be // done under a WriteLock - which is why we didn't do it immediately. if (_proposedAllListenersList == list) { using (WriteLock) { // test again, in case another thread changed _proposedAllListersList. if (_proposedAllListenersList == list) { HybridDictionary dict = (HybridDictionary)this[sender]; if (dict != null) { dict[AllListenersKey] = list; } _proposedAllListenersList = null; } // Another thread could have changed _proposedAllListersList // since we set it (earlier in this method), either // because it calculated a new one while handling a PropertyChanged(""), // or because it added/removed/purged a listener. // In that case, we will simply abandon our proposed list and we'll // have to compute it again the next time. But that only happens // if there's thread contention. It's not worth doing something // more complicated just for that case. } } }
public void Run(string[] args) { if (args.Length == 0) { Help(); return; } var e = args.GetEnumerator(); while (e.MoveNext()) { var a = ((string)e.Current).ToLowerInvariant(); if (a == "-help" || a == "-h" || a == "-?") { Help(); return; } else if (a == "-output" || a == "-out") { if (e.MoveNext()) { ViewFactory.Builder.SetPath((string)e.Current); View = ViewFactory.CreateView(); } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } } else if (a == "-target") { if (e.MoveNext()) { target = new ConnectionTarget(); if (!target.Parse((string)e.Current)) { throw new Exception(BAD_TARGET); } } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } } else if (a == "-address" || a == "-addr") { if (e.MoveNext()) { if (target == null) { throw new Exception(NO_TARGET); } target.Address = (string)e.Current; } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } } else if (a == "-port") { if (e.MoveNext()) { nonSecurePort = int.Parse((string)e.Current); } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } if (nonSecurePort <= 0 || 65536 <= nonSecurePort) { throw new Exception(BAD_NPORT); } } else if (a == "-secureport" || a == "-secport") { if (e.MoveNext()) { securePort = int.Parse((string)e.Current); } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } if (securePort <= 0 || 65536 <= securePort) { throw new Exception(BAD_SPORT); } } else if (a == "-certpath") { if (e.MoveNext()) { certificatePath = (string)e.Current; } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } } else if (a == "-certpassword" || a == "-certpasswd" || a == "-certpass") { if (e.MoveNext()) { certificatePassword = (string)e.Current; } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } } else if (a == "-shutdown") { commandRequest = "shutdown"; } else if (a == "-commandtarget" || a == "-cmdtarget") { if (e.MoveNext()) { commandTarget = (string)e.Current; } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } var ss = commandTarget.Split(new char[] { ':' }); if (ss.Length == 2) { commandTarget = ss[0]; commandPort = int.Parse(ss[1]); } else if (ss.Length != 1) { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } } else if (a == "-commandport" || a == "-cmdport") { if (e.MoveNext()) { commandPort = int.Parse((string)e.Current); } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } } #if DEBUG else if (a == "-debug") { System.Diagnostics.Debugger.Launch(); } #endif else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } } if (target != null) { if (nonSecurePort == 0 && target.Type == ConnectionType.Raw) { nonSecurePort = HttpConstants.HTTP_PORT; } if (nonSecurePort > 0) { var nonSecureListener = new NonSecureListener() { Destination = target, Port = nonSecurePort }; ListenerList.Add(nonSecureListener); } if ((certificatePath != null && certificatePassword == null) || (certificatePath == null && certificatePassword != null)) { throw new Exception(CERTIFICATE_PATH_AND_PASSWORD); } if (securePort == 0 && (target.Type == ConnectionType.Encrypted || certificatePath != null)) { securePort = HttpConstants.HTTPS_PORT; } if (securePort > 0) { if (certificatePath == null || certificatePassword == null) { throw new Exception(CERTIFICATE_PATH_AND_PASSWORD); } var secureListener = new SecureListener() { Destination = target, Port = securePort, ServerCertificatePath = certificatePath, ServerCertificatePassword = certificatePassword }; ListenerList.Add(secureListener); } } if (ListenerList.Count > 0) { if (commandRequest != null) { throw new Exception(EXCLUSIVE_REQUESTS); } var commandListener = new CommandListener() { Port = commandPort, OnShutdown = ShutDown }; ListenerList.Add(commandListener); foreach (var listener in ListenerList) { listener.Start(); } TerminateEvent.WaitOne(); foreach (var listener in ListenerList) { listener.Stop(); } foreach (var listener in ListenerList) { listener.Wait(); } } else if (commandRequest != null) { var commandClient = new CommandClient() { Hostname = commandTarget, Port = commandPort }; commandClient.Send(commandRequest); } else { throw new Exception(BAD_COMMAND_LINE_SYNTAX); } }
/// <summary> /// Purge dead entries.</summary> /// <returns>True if any entries were purged, otherwise false</returns> public bool Purge() { ListenerList.PrepareForWriting(ref m_listeners); return(m_listeners.Purge()); }