/// <summary> /// Register subscriber using a string token, which is usually defined as a constant. /// Subscriber performs internal notifications. /// </summary> /// <param name="token">String identifying a message token</param> /// <param name="subscriber">Subscriber requesting notifications</param> public void Register(string token, INotifyable subscriber) { lock (_sharedLock) { // Add token if not present if (!_subscriptions.ContainsKey(token)) { _subscriptions.Add(token, new List <WeakReference> { new WeakReference(subscriber) }); return; } // Get subscribers for this token List <WeakReference> weakSubscribers; if (_subscriptions.TryGetValue(token, out weakSubscribers)) { // See if subcriber is already present var existing = (from w in weakSubscribers where w != null && w.IsAlive && ReferenceEquals(w.Target, subscriber) select w).SingleOrDefault(); // Add if subcriber is already present if (existing == null) { _subscriptions[token].Add(new WeakReference(subscriber)); } } } }
/// <summary> /// Remove subscriber from the invocation list /// </summary> /// <param name="token">String identifying a message token</param> /// <param name="subscriber">Subscriber to remove from notifications</param> public void Unregister(string token, INotifyable subscriber) { lock (_sharedLock) { List <WeakReference> weakSubscribers; if (_subscriptions.TryGetValue(token, out weakSubscribers)) { // Find subscriber WeakReference weakSubscriber = weakSubscribers .SingleOrDefault(w => w.IsAlive && ReferenceEquals (w.Target, subscriber)); // Remove subscriber if (weakSubscriber != null) { weakSubscribers.Remove(weakSubscriber); } // Remove dictionary entry if no subscibers left if (_subscriptions[token].Count == 0) { _subscriptions.Remove(token); } } } }
public Buffer SetState(QpcTimeStamp qpcTimeStamp, BufferState state, string reason) { BufferState entryState = State; State = state; TimeStamp = qpcTimeStamp; switch (state) { case BufferState.SendPosted: CopyHeaderToByteArray(); SendPostedTimeStamp = qpcTimeStamp; break; case BufferState.Received: UpdateHeaderFromByteArray(); break; default: break; } if (StateEmitter.IsEnabled) { StateEmitter.Emit("{0} State changed to {1} [from: {2}, reason: {3}]", BufferName, state, entryState, reason ?? "NoReasonGiven"); } INotifyable notifyOnStateChange = NotifyOnSetState; if (notifyOnStateChange != null) { notifyOnStateChange.Notify(); } return(this); }
public SerialEchoTracker(string portPartID, string portTargetSpec, double[] binBoundariesArray, SerialEchoPerformancePartConfig config, INotifyable notifyOnDone, Logging.IBasicLogger logger) { PortTargetSpec = portTargetSpec; Config = config; NotifyOnDone = notifyOnDone; Logger = logger; h = new Histogram(binBoundariesArray); timeoutCountGPI = new MDRF.Writer.GroupPointInfo() { Name = "timeoutCount", ValueCST = ContainerStorageType.UInt64, VC = new ValueContainer(0L) }; failureCountGPI = new MDRF.Writer.GroupPointInfo() { Name = "failureCount", ValueCST = ContainerStorageType.UInt64, VC = new ValueContainer(0L) }; hGrp = new MDRFHistogramGroupSource("{0}".CheckedFormat(portPartID), h, (ulong)config.AggregateGroupsFileIndexUserRowFlagBits, extraClientNVS: new NamedValueSet() { { "SerialEcho" }, { "PortTargetSpec", PortTargetSpec } }, extraGPISet: new[] { timeoutCountGPI, failureCountGPI }); try { portConfig = new PortConfig(portPartID, portTargetSpec) { TxLineTerm = LineTerm.None, RxLineTerm = LineTerm.CR, ConnectTimeout = (2.0).FromSeconds(), WriteTimeout = (1.0).FromSeconds(), ReadTimeout = (1.0).FromSeconds(), IdleTime = (1.0).FromSeconds(), EnableAutoReconnect = true, }; port = MosaicLib.SerialIO.Factory.CreatePort(portConfig); portGetNextPacketAction = port.CreateGetNextPacketAction(); portFlushAction = port.CreateFlushAction(); portWriteAction = port.CreateWriteAction(portWriteActionParam = new WriteActionParam()); } catch (System.Exception ex) { Logger.Error.Emit("Port setup for '{0}' failed: {1}", portTargetSpec, ex.ToString(ExceptionFormat.TypeAndMessage)); } }
private void InternalNotify(string token, object sender, NotificationEventArgs e, bool post) { // Get weak subscribers List <WeakReference> weakSubscribers; lock (_sharedLock) { if (!_subscriptions.TryGetValue(token, out weakSubscribers)) { return; } // Make a copy while locked weakSubscribers = weakSubscribers.ToList(); } // Get compatible living subscribers var subscribers = from w in weakSubscribers let s = w.Target as INotifyable where w != null && w.IsAlive && s != null select s; // Invoke each callback associated with token foreach (var subscriber in subscribers) { INotifyable subscriber1 = subscriber; SafeNotify(() => subscriber1.Notify(token, sender, e)); } lock (_sharedLock) { if (_subscriptions.ContainsKey(token)) { // Remove subscribers who are no longer alive var deadSubscribers = weakSubscribers .Where(w => w == null || !w.IsAlive); foreach (var s in deadSubscribers) { _subscriptions[token].Remove(s); } // Remove dictionary entry if no subscibers left if (_subscriptions[token].Count == 0) { _subscriptions.Remove(token); } } } }
/// <summary> /// Sets the byteCount to the headerSize and sets the header's BufferSeqNum to zero. /// </summary> public void Clear(QpcTimeStamp qpcTimeStamp, bool clearByteArrayContents = false, string reason = null) { header = BufferHeaderV1.Empty; byteCount = header.Length; Message = null; NotifyOnSetState = null; if (clearByteArrayContents) { System.Array.Clear(byteArray, 0, byteArraySize); } SetState(qpcTimeStamp, Buffers.BufferState.Clear, reason); }
public Buffer Update(PurposeCode?purposeCode = null, BufferHeaderFlags?orInFlags = null, ulong?seqNum = null, int?byteCount = null, ulong?ackSeqNum = null, INamedValueSet buildPayloadDataFromE005NVS = null, bool throwOnException = false, byte[] copyPayloadDataFromByteArray = null, INotifyable notifyOnSetState = null) { if (purposeCode != null) { header.PurposeCode = purposeCode ?? PurposeCode.None; } if (orInFlags != null) { header.Flags |= orInFlags ?? BufferHeaderFlags.None; } if (seqNum != null) { SeqNum = seqNum ?? 0; } if (byteCount != null) { this.byteCount = byteCount ?? 0; } if (ackSeqNum != null) { header.AckSeqNum = ackSeqNum ?? 0; } if (buildPayloadDataFromE005NVS != null) { header.Flags |= BufferHeaderFlags.BufferContainsE005NVS; copyPayloadDataFromByteArray = buildPayloadDataFromE005NVS.ConvertToE005Data(throwOnException: throwOnException); } if (copyPayloadDataFromByteArray != null) { byteArray.SafeCopyFrom(header.Length, copyPayloadDataFromByteArray); this.byteCount = Math.Min(header.Length + copyPayloadDataFromByteArray.Length, byteArraySize); } if (notifyOnSetState != null) { NotifyOnSetState = notifyOnSetState; } return(this); }
/// <summary>Adds/Replaces the indicated socket, settings and notification target to the monitor list and starts the background service thread if it is not already running.</summary> public void AddSocketToList(Socket s, bool read, bool write, bool error, INotifyable notifyTarget) { TableItem tableItem = new TableItem() { Socket = s, read = read, write = write, error = error, notifyTarget = notifyTarget, }; string notUsableReason = tableItem.NotUsableReason; if (!notUsableReason.IsNullOrEmpty()) { tableItem.LastLoggedNotUsableReason = notUsableReason; Logger.Debug.Emit("{0} given unusable socket {1} : {2} [Adding inactive]", Fcns.CurrentMethodName, tableItem.shAsInt64, notUsableReason); } lock (userTableMutex) { // the following passes ownership of the tableItem to this object's service thread. userTableDictionary[s] = tableItem; notifyOnNextTableRebuildTableItemList.Add(tableItem); rebuildTablesFromUserTable = true; NumActiveSockets += 1; } StartBackgroundThreadIfNeeded(); threadWaitEventNotifier.Notify(); }
public PingTracker(string hostNameOrAddress, double[] binBoundariesArray, PingPerformancePartConfig config, INotifyable notifyOnDone) { HostNameOrAddress = hostNameOrAddress; NotifyOnDone = notifyOnDone; // calling GetHostAddresses can throw for many reasons (invalid app.config for example...) Func <System.Net.IPAddress []> getHostAddressesDelegate = () => System.Net.Dns.GetHostAddresses(hostNameOrAddress); IPAddressArray = getHostAddressesDelegate.TryGet(); IPAddress = IPAddressArray.SafeAccess(0, System.Net.IPAddress.None); h = new Histogram(binBoundariesArray); timeoutCountGPI = new MDRF.Writer.GroupPointInfo() { Name = "timeoutCount", ValueCST = ContainerStorageType.UInt64, VC = new ValueContainer(0L) }; failureCountGPI = new MDRF.Writer.GroupPointInfo() { Name = "failureCount", ValueCST = ContainerStorageType.UInt64, VC = new ValueContainer(0L) }; hGrp = new MDRFHistogramGroupSource("hPing_{0}".CheckedFormat(HostNameOrAddress), h, (ulong)config.AggregateGroupsFileIndexUserRowFlagBits, extraClientNVS: new NamedValueSet() { { "Ping" }, { "Host", HostNameOrAddress }, { "IPAddress", IPAddress.ToString() } }, extraGPISet: new[] { timeoutCountGPI, failureCountGPI }); extraData = new byte[config.ExtraLength]; responseTimeLimitInMSec = unchecked ((int)config.ResponseTimeLimit.TotalMilliseconds); responseWaitTimeLimit = (config.ResponseTimeLimit.TotalSeconds + 0.25).FromSeconds(); }
/// <summary>Adds/Replaces the indicated socket, settings and notification target to the monitor list and starts the background service thread if it is not already running.</summary> public void AddSocketToList(Socket s, bool read, bool write, bool error, INotifyable notifyTarget) { TableItem tableItem = new TableItem() { s = s, read = read, write = write, error = error, notifyTarget = notifyTarget }; lock (userTableMutex) { userTableDictionary[s] = tableItem; rebuildTablesFromUserTable = true; } StartBackgroundThreadIfNeeded(); }
/// <summary> /// Obtains the ISharedDispatcherTimer instance from the dictionary (createing one if needed), /// Adds any of the optional Tick event handler signatures (as supported by the ISharedDispatchTimer's TickNotificationList) /// and returns an IDisposable token that will release use of the timer and will remove any given Tick event handler signatures from the underlying TickNotificationList when the token is dipsosed. /// </summary> public static IDisposable GetAndStartSharedTimer(double rate, string clientName, BasicNotificationDelegate onTickNotifyDelegate = null, INotifyable notifyableTarget = null, System.Threading.EventWaitHandle eventWaitHandle = null) { ISharedDispatcherTimer sharedDispatcherTimer = GetSharedTimer(rate); if (onTickNotifyDelegate != null) { sharedDispatcherTimer.TickNotificationList.OnNotify += onTickNotifyDelegate; } if (notifyableTarget != null) { sharedDispatcherTimer.TickNotificationList.AddItem(notifyableTarget); } if (eventWaitHandle != null) { sharedDispatcherTimer.TickNotificationList.AddItem(eventWaitHandle); } IDisposable token = sharedDispatcherTimer.GetRunTimerToken(clientName); return(new ExplicitDisposeActionList() .AddItems(() => Fcns.DisposeOfGivenObject(token), () => { if (onTickNotifyDelegate != null) { sharedDispatcherTimer.TickNotificationList.OnNotify -= onTickNotifyDelegate; } if (notifyableTarget != null) { sharedDispatcherTimer.TickNotificationList.RemoveItem(notifyableTarget); } if (eventWaitHandle != null) { sharedDispatcherTimer.TickNotificationList.RemoveItem(eventWaitHandle); } })); }