PostSharp.Samples / PostSharp.Samples.Profiling / ThreadLocalSampleCollector.cs
using System;
using System.Collections.Generic;
using System.Threading;
 
namespace PostSharp.Samples.Profiling
{
  internal class ThreadLocalSampleCollector
  {
    private readonly Thread _ownerThread = Thread.CurrentThread;
    private MetricAccessor[] _metrics = new MetricAccessor[1024];
    private readonly SampleCollector _parent;
    private readonly Stack<MetricAccessor> _contextStack = new Stack<MetricAccessor>();
 
    public ThreadLocalSampleCollector(SampleCollector parent)
    {
      this._parent = parent;
    }
 
    public void EnterMethod(MetricMetadata method)
    {
      this._contextStack.Push(this.GetAccessor(method));
    }
 
    public void ExitMethod(MetricMetadata method, in ExcludedTimeData excludedData)
    {
      if (this._contextStack.Pop().Metadata != method)
      {
        throw new InvalidOperationException();
      }
 
      if (_contextStack.Count > 0)
      {
        var parentContext = _contextStack.Peek();
        parentContext.AddExclusion(excludedData);
      }
 
    }
 
    public bool GetSample(MetricMetadata method, out MetricData data)
    {
      MetricAccessor metric;
      if (this._metrics.Length <= method.Index || (metric = this._metrics[method.Index]) == null)
      {
        data = default;
        return false;
      }
      else
      {
        metric.GetData(out data);
        return true;
      }
    }
 
    public void AddSample(MetricMetadata method, in MetricData data)
    {
 
 
 
      var sampleAccessor = GetAccessor(method);
 
      sampleAccessor.AddData(data);
 
    }
 
    private MetricAccessor GetAccessor(MetricMetadata method)
    {
#if DEBUG
      if (this._ownerThread != Thread.CurrentThread)
      {
        throw new InvalidOperationException("Cannot get a mutable MetricAccessor from a different thread than the owner thread.");
      }
#endif
 
      if (this._metrics.Length <= method.Index)
      {
        Array.Resize(ref this._metrics, ((this._parent.ProfiledMethodCount / 1024) + 1) * 1024);
      }
 
      var sampleAccessor = this._metrics[method.Index];
      if (sampleAccessor == null)
      {
        this._metrics[method.Index] = sampleAccessor = new MetricAccessor(method);
      }
 
      return sampleAccessor;
    }
  }
}