Nonblocking Pool Class
November 20th, 2005

This is not an original idea but I thought I would post/explain it anyway. This is a generalized version of a pattern I have been using for a while. I’m not sure where I first picked it up but I’ve seen it used in several places.

The purpose of this class is to pool instances of a particular type in a server application. The assumptions I am making about the problem are:

  • It is both possible and worthwhile to reuse instances of a certain type. Types that may fit this criteria are large arrays of primitive types, types that hold unmanaged or scarce resources such as connections, et al. Not all types fit this criteria, obviously.
  • It is more undesirable to have a thread enter a waiting state (fail to acquire a lock, in other words) than it is to create a new instance of the type being reused. That would be the case if the instances are somewhat cheap but the average request or call time to your server is relatively long.

The nice thing about this pool class is that it handles the second case gracefully. It will reuse objects as much as possible, but it won’t block a thread in the case that the attempt fails. If it didn’t, you might end up introducing massive contention in your attempt to increase throughput with a different, locking pool.

The class provides very lightweight synchronization using atomic operations - there’s no use of critical sections (the lock keyword).

/// <summary>
/// Provides and reuses objects of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">
/// The type that is pooled. Must provide a default constructor.
/// </typeparam>
public class NonBlockingPool<T>
   where T : new()
{
   // Contains the pooled items.
   private Stack<T> _stack;

   // The maximum size of _stack.
   private int _max;

   // This reference is used to ensure that only one thread
   // calls methods on _stack at a time.
   private object _lock = new object();

   /// <summary>
   /// Gets or sets the maximum size of the pool.
   /// </summary>
   public int MaximumSize
   {
      get { return _max; }
      set { _max = value; }
   }

   /// <summary>
   /// Gets a pooled instance of type <typeparamref name="T"/>,
   /// or yields a new instance.
   /// </summary>
   public T Get()
   {
      // If two threads enter this method at the same time,
      // only one will acquire _lock (the other will be given
      // null). The caller that fails to acquire _lock will
      // be returned a new instance of T.
      T ret = default(T);
      object obj = Interlocked.Exchange(ref _lock, null);
      try
      {
         if (obj != null && _stack.Count > 0)
         {
            ret = _stack.Pop();
         }
         else
         {
            ret = new T();
         }
      }
      finally
      {
         if (obj != null)
         {
            _lock = obj;
         }
      }
      return ret;
   }

   /// <summary>
   /// Reuses an instance of type <paramref name="T"/> in a
   /// subsequent request or call whenever possible.
   /// </summary>
   public void Reuse(T t)
   {
      // If two threads enter this method at the same time,
      // only one will acquire _lock (the other will be given
      // a null reference). The instance of T provided by
      // the losing thread will just be collected and not
      // reused.
      object obj = Interlocked.Exchange(ref _lock, null);
      try
      {
         if (obj != null && _stack.Count < _max)
         {
            _stack.Push(t);
         }
      }
      finally
      {
         if (obj != null)
         {
            _lock = obj;
         }
      }
   }

   /// <summary>
   /// Constructor.
   /// </summary>
   /// <param name="max">
   /// The maximum number of instances of
   /// <typeparamref name="T"/> to hold in the pool.
   /// </param>
   public NonBlockingPool(int max)
   {
      if (max < 0)
      {
         throw new ArgumentOutOfRangeException("max");
      }
      _stack = new Stack<T>(max);
      _max = max;
   }
}

Here’s a (contrived) minimal example of a consumer of such a pool. This server class makes a context object available to each thread for the duration of each request. This object is stored in a slot unique to each thread (specified with the ThreadStaticAttribute) while a ProcessRequest function is called. The instance is returned to the pool in a finally block after that call is finished.

public class SampleServer
{
   [ThreadStatic]
   private static ServerContext _context;

   private NonBlockingPool<ServerContext> _pool;

   public static ServerContext Context
   {
      get { return _context; }
   }

   internal void ProcessRequest(IServerApp app)
   {
      try
      {
         _context = _pool.Get();
         app.ProcessRequest();
      }
      finally
      {
         if (_context != null)
         {
            _context.Reset();
            _pool.Reuse(_context);

            // We want the context to be collected if it isn't
            // actually reused by the pool.
            _context = null;
         }
      }
   }
}

A more concrete example might be an IHttpModule or a remoting server channel sink. As I said once already, it’s important to consider 1) the type of resource you are pooling and 2) the amount of load your application is expecting before committing yourself to a pattern such as this one.


Hammer Hank Goldberg
November 20th, 2005

If 8:50 on Monday night—the “JACKED UP” NFL Primetime segment—is the best five minutes of television all week, then I think there are really only two contenders for the worst.

  • That sycophant Michael Irvin’s weekly fawning human interest story on NFL Countdown.
  • “Hammerin” Hank Goldberg’s picks against the spread at the end of the 10:30 Sportscenter.

I’m going to discount the ESPN Sunday Night game in its entirety. It is more like slow, drawn out water torture than a sudden and effective “stupid stick beating.” I don’t want to defend Michael “I talked to T.O. and he said…” Irvin in any way, but I think Goldberg is much worse. In the words of Paul Maguire, “I’m a tell you what.”

I’m not a gambler, but I know this: it is not a skill to pick games at .500 against the spread. You are supposed to be able to do that. Hence the spread. Although Hank is usually below the .500 mark, it is not by a statistically significant margin. In other words, you could not short his picks and make money, either.

Add to this annoyance his penchant for citing ridiculous, obscure statistics as excuses for his abysmal performance.

I would have done a lot better last week if I had remembered that Arizona was only winning 25% of the time after two wins on the road against east coast teams, or that Chicago has won their last two when the wind was southeasterly and above 20 miles per hour.

I made that quote up. Watch his segment next week and see if you can tell the difference. I am completely unable to explain why this human paraquat is allowed to return year after year.


Press Innumeracy
November 16th, 2005

I just finished reading this Reuters story, “Rising Sea Levels Threaten New Jersey.” Nevermind the obvious question of whether we’d really be menaced by the disappearance of New Jersey. I would like to focus on details tangential to the main story, as is my custom.

Notice the next-to-last paragraph,

Worldwide, sea levels are expected to rise between 0.09 and 0.88 meter (0.29 and 2.88 feet) between 1990 and 2100, the report said, citing figures from the Intergovernmental Panel on Climate Change.

Do you see anything amiss? Many scientists and engineers in the audience have already leapt out of their seats. I will explain the problem anyway, for those of you trained in the humanities.

The issue is one of precision. Or rather, too much of it.

What most likely occurred is that the Journalism major who wrote this lifted the metric figures from the published paper. Writing for a U.S. audience, he obviously needed English equivalents.

If you plug 0.09 and 0.88 meters through a conversion calculator, you get 0.29527559055118110236220472440945 feet and 2.8871391076115485564304461942257 feet, respectively. The author made the rookie mistake of cutting these off at the same number of decimal places.

This author, like most reporters, does not understand significant figures. The trouble is that the metric numbers quoted give one and two significant digits, respectively. His converted numbers erroneously give two and three significant digits.

I have gone to the trouble of rewriting his paragraph for him.

Worldwide, sea levels are expected to rise between 0.09 and 0.88 meter (0.3 and 2.9 feet) between 1990 and 2100, the report said, citing figures from the Intergovernmental Panel on Climate Change.

You may think that this is a silly thing for me to be complaining about. Not so. Significant digits are one of the first lessons in every science class, from elementary school through the first few semesters of college. Anyone doing science reporting should at least be familiar with significant digits.

Given this, it is not difficult to understand why there is so much confused and idiotic coverage of the Dover Design trial (I am on board with refusing to call it “Intelligent”) and why it is reported at least once a year that the speed of light has been exceeded (Everyone say it together with me: “Phase velocity vs Group velocity”).