private static TrackingFrame MaxNpv(TrackingFrame frame) { if (_maxNpv.Count == 0) { _maxNpv.Add(frame); return(frame); } var npv = Total(FundedToBoolArray(frame.Funded), Npv); var maxNpv = Total(FundedToBoolArray(_maxNpv[0].Funded), Npv); if (npv > maxNpv) { _maxNpv = new List <TrackingFrame> { frame } } ; if (npv == maxNpv) { _maxNpv.Add(frame); } return(_maxNpv[0]); }
private IRedisClient TrackInstance(MethodBase callingMethodType, string method, IRedisClient instance) { // track var frame = new TrackingFrame() { Id = Guid.NewGuid(), Initialised = DateTime.Now, ProvidedToInstanceOfType = callingMethodType.DeclaringType, }; lock (this.trackingFrames) { this.trackingFrames.Add(frame); } // proxy var proxy = new TrackingRedisClientProxy(instance, frame.Id); proxy.BeforeInvoke += (sender, args) => { if (string.Compare("Dispose", args.MethodInfo.Name, StringComparison.InvariantCultureIgnoreCase) != 0) { return; } lock (this.trackingFrames) { this.trackingFrames.Remove(frame); } var duration = DateTime.Now - frame.Initialised; Logger.DebugFormat("{0,18} Disposed {1} released from instance of type {2} checked out for {3}", method, frame.Id, frame.ProvidedToInstanceOfType.FullName, duration); }; Logger.DebugFormat("{0,18} Tracking {1} allocated to instance of type {2}", method, frame.Id, frame.ProvidedToInstanceOfType.FullName); return proxy.GetTransparentProxy() as IRedisClient; }
/// <summary> /// Gets <see cref="TrackingFrame"/> from the queue with the specified timestamp, in ticks. If no frame exists for /// the specified timestamp, one will be created. /// </summary> /// <param name="ticks">Timestamp, in ticks, for which to get or create <see cref="TrackingFrame"/>.</param> /// <remarks> /// Ticks can be any point in time so long time requested is greater than time of last published frame; this queue is /// used in a real-time scenario with time moving forward. If a frame is requested for an old timestamp, null will /// be returned. Note that frame returned will be "best-fit" for given timestamp based on <see cref="FramesPerSecond"/>. /// </remarks> /// <returns>An existing or new <see cref="TrackingFrame"/> from the queue for the specified timestamp.</returns> public TrackingFrame GetFrame(long ticks) { // Calculate destination ticks for this frame TrackingFrame frame = null; bool locked = false, nodeAdded = false; long baseTicks, ticksBeyondSecond, frameIndex, destinationTicks, nextDestinationTicks; // Baseline timestamp to the top of the second baseTicks = ticks - ticks % Ticks.PerSecond; // Remove the seconds from ticks ticksBeyondSecond = ticks - baseTicks; // Calculate a frame index between 0 and m_framesPerSecond-1, corresponding to ticks // rounded down to the nearest frame frameIndex = (long)(ticksBeyondSecond / m_ticksPerFrame); // Calculate the timestamp of the nearest frame rounded up nextDestinationTicks = (frameIndex + 1) * Ticks.PerSecond / m_framesPerSecond; // Determine whether the desired frame is the nearest // frame rounded down or the nearest frame rounded up if (m_timeResolution <= 1) { if (nextDestinationTicks <= ticksBeyondSecond) destinationTicks = nextDestinationTicks; else destinationTicks = frameIndex * Ticks.PerSecond / m_framesPerSecond; } else { // If, after translating nextDestinationTicks to the time resolution, it is less than // or equal to ticks, nextDestinationTicks corresponds to the desired frame if ((nextDestinationTicks / m_timeResolution) * m_timeResolution <= ticksBeyondSecond) destinationTicks = nextDestinationTicks; else destinationTicks = frameIndex * Ticks.PerSecond / m_framesPerSecond; } // Recover the seconds that were removed destinationTicks += baseTicks; // Make sure ticks are newer than latest published ticks... if (destinationTicks > Thread.VolatileRead(ref m_publishedTicks)) { // See if requested frame is already available (can do this outside lock with concurrent dictionary) if (m_frameHash.TryGetValue(destinationTicks, out frame)) return frame; // Didn't find frame for this timestamp so we need to add a new one to the queue try { m_queueLock.Enter(ref locked); // Another thread may have gotten to this task already, so check for this contingency... if (m_frameHash.TryGetValue(destinationTicks, out frame)) return frame; // Create a new frame for this timestamp frame = new TrackingFrame(m_createNewFrame(destinationTicks), m_downsamplingMethod); if (m_frameList.Count > 0) { // Insert frame into proper sorted position... LinkedListNode<TrackingFrame> node = m_frameList.Last; do { if (destinationTicks > node.Value.Timestamp) { m_frameList.AddAfter(node, frame); nodeAdded = true; break; } node = node.Previous; } while (node != null); } if (!nodeAdded) { m_frameList.AddFirst(frame); m_head = frame; } // Since we'll be requesting this frame over and over, we'll use // a hash table for quick frame lookups by timestamp m_frameHash[destinationTicks] = frame; } finally { if (locked) m_queueLock.Exit(); } } return frame; }
/// <summary> /// Removes current <see cref="Head"/> frame from the <see cref="FrameQueue"/> after it has been processed and assigns a new <see cref="Head"/>. /// </summary> public void Pop() { // We track latest published ticks - don't want to allow slow moving measurements // to inject themselves after a certain publication timeframe has passed - this // avoids any possible out-of-sequence frame publication... m_last = m_head; m_head = null; long publishedTicks = m_last.Timestamp; Thread.VolatileWrite(ref m_publishedTicks, publishedTicks); bool locked = false; // Assign next node, if any, as quickly as possible. Still have to wait for queue // lock - tick-tock, time's-a-wastin' and user function needs a frame to publish. try { m_queueLock.Enter(ref locked); if (m_frameList.Count > 0) { LinkedListNode<TrackingFrame> nextNode = m_frameList.First.Next; // If next frame is available, go ahead and assign it... if (nextNode != null) m_head = nextNode.Value; // Clean up frame queues m_frameList.RemoveFirst(); } } finally { if (locked) m_queueLock.Exit(); } TrackingFrame frame; m_frameHash.TryRemove(publishedTicks, out frame); }
/// <summary> /// Releases the unmanaged resources used by the <see cref="FrameQueue"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { Clear(); m_frameList = null; m_frameHash = null; m_createNewFrame = null; m_head = null; m_last = null; } } finally { m_disposed = true; // Prevent duplicate dispose. } } }
private void InitializeTrackingFrame() { string trackingPage = GetWebViewUrl(); trackingFrame = new TrackingFrame(trackingPage); }
/// <summary> /// Gets <see cref="TrackingFrame"/> from the queue with the specified timestamp, in ticks. If no frame exists for /// the specified timestamp, one will be created. /// </summary> /// <param name="ticks">Timestamp, in ticks, for which to get or create <see cref="TrackingFrame"/>.</param> /// <remarks> /// Ticks can be any point in time so long time requested is greater than time of last published frame; this queue is /// used in a real-time scenario with time moving forward. If a frame is requested for an old timestamp, null will /// be returned. Note that frame returned will be "best-fit" for given timestamp based on <see cref="FramesPerSecond"/>. /// </remarks> /// <returns>An existing or new <see cref="TrackingFrame"/> from the queue for the specified timestamp.</returns> public TrackingFrame GetFrame(long ticks) { // Calculate destination ticks for this frame TrackingFrame frame = null; bool nodeAdded = false; long baseTicks, ticksBeyondSecond, frameIndex, destinationTicks, nextDestinationTicks; // Baseline timestamp to the top of the second baseTicks = ticks - ticks % Ticks.PerSecond; // Remove the seconds from ticks ticksBeyondSecond = ticks - baseTicks; // Calculate a frame index between 0 and m_framesPerSecond-1, corresponding to ticks // rounded down to the nearest frame frameIndex = (long)(ticksBeyondSecond / m_ticksPerFrame); // Calculate the timestamp of the nearest frame rounded up nextDestinationTicks = (frameIndex + 1) * Ticks.PerSecond / m_framesPerSecond; // Determine whether the desired frame is the nearest // frame rounded down or the nearest frame rounded up if (m_timeResolution <= 1) { if (nextDestinationTicks <= ticksBeyondSecond) destinationTicks = nextDestinationTicks; else destinationTicks = frameIndex * Ticks.PerSecond / m_framesPerSecond; } else { // If, after translating nextDestinationTicks to the time resolution, it is less than // or equal to ticks, nextDestinationTicks corresponds to the desired frame if ((nextDestinationTicks / m_timeResolution) * m_timeResolution <= ticksBeyondSecond) destinationTicks = nextDestinationTicks; else destinationTicks = frameIndex * Ticks.PerSecond / m_framesPerSecond; } // Recover the seconds that were removed destinationTicks += baseTicks; // Make sure ticks are newer than latest published ticks... if (destinationTicks > m_publishedTicks) { // Wait for queue lock - we wait because calling function demands a destination frame lock (m_frameList) { // See if requested frame is already available... if (m_frameHash.TryGetValue(destinationTicks, out frame)) return frame; // Didn't find frame for this timestamp so we create one frame = new TrackingFrame(m_createNewFrame(destinationTicks), m_downsamplingMethod); if (m_frameList.Count > 0) { // Insert frame into proper sorted position... LinkedListNode<TrackingFrame> node = m_frameList.Last; do { if (destinationTicks > node.Value.Timestamp) { m_frameList.AddAfter(node, frame); nodeAdded = true; break; } node = node.Previous; } while (node != null); } if (!nodeAdded) { m_frameList.AddFirst(frame); m_head = frame; } // Since we'll be requesting this frame over and over, we'll use // a hash table for quick frame lookups by timestamp m_frameHash.Add(destinationTicks, frame); } } return frame; }
/// <summary> /// Removes current <see cref="Head"/> frame from the <see cref="FrameQueue"/> after it has been processed and assigns a new <see cref="Head"/>. /// </summary> public void Pop() { // We track latest published ticks - don't want to allow slow moving measurements // to inject themselves after a certain publication timeframe has passed - this // avoids any possible out-of-sequence frame publication... m_last = m_head; m_head = null; m_publishedTicks = m_last.Timestamp; // Assign next node, if any, as quickly as possible. Still have to wait for queue // lock - tick-tock, time's-a-wastin' and user function needs a frame to publish. lock (m_frameList) { LinkedListNode<TrackingFrame> nextNode = m_frameList.First.Next; // If next frame is available, go ahead and assign it... if (nextNode != null) m_head = nextNode.Value; // Clean up frame queues m_frameList.RemoveFirst(); m_frameHash.Remove(m_publishedTicks); } }