Posts for #C#

This is the sixth article in my mini series about object pooling. Be sure to read part 1, part 2, part 3, part 4 and part 5 first. It took me a while to find the time for the next article, but here it is. Now we’re finally going to deal with the topic of growing and shrinking the pool. One of the first questions we have to ask when it comes to this is, when are we going to do it? We have one mechanism for growing the pool implemented already, which takes place when, during a call to the GetObject method, no unused object can be found in the pool. But is this the right place to think about growing, really? And what about shrinking? I think it’s a good idea to keep these things out of the way of “normal call flow”. Meaning, if possible, a client’s call to get an object from the pool shouldn’t be delayed by management work. So I have implemented the mechanism with the help of a timer: a regular check is executed to find whether the number of used objects in the pool is too high or too low and growing or shrinking is done accordingly. To classify the number of used objects as “too high” or “too low”, I’ve introduced two properties HighWaterMark and LowWaterMark. These are percentage values: if the percentage of used objects in the pool is higher than HighWaterMark, the pool is considered too small and vice versa. To prevent the pool size from being scaled up and down wildly in certain scenarios, I have also introduced threshold values – so the percentage has to be found to be too high at more than one check in a row, for example, for the pool to be grown. Actually, the threshold is more useful in the shrinking than the growing case, but it’s the same principle. So, here’s the code for these changes. The next article will introduce a sample program to test all the functionality that’s implemented so far and I’ll post the source code for the pool and the sample with it. So if you haven’t been typing in all this code yourself, stay tuned for the next installment in the series!

class Pool<T> {
  // ...

  private Pool( ) {
    pool = new List<Slot>( );
    retryWaitTime = 500;
    poolExtensionBatchSize = 10;
    poolExtensionBatchSizeIsPercent = true;
    maxGetObjectTries = 5;
    outOfObjectsBehaviour = OutOfObjectsBehaviour.ExtendPool;
    delayObjectCreation = false;
    maxPoolSize = 100;
    lowWaterMark = 20;
    highWaterMark = 80;
    resizingWaitTime = 2000;
    growThreshold = 0;
    shrinkThreshold = 3;
  }

  Timer resizingTimer;
  object resizingTimerLock = new object( );

  private bool useTimerBasedResizing;
  /// <summary>
  /// Gets or sets a value indicating whether the pool checks for low and high
  /// water situations automatically and regularly. Also see ResizingWaitTime.
  /// </summary>
  public bool UseTimerBasedResizing {
    get {
      return useTimerBasedResizing;
    }
    set {
      if (useTimerBasedResizing != value) {
        useTimerBasedResizing = value;
        lock (resizingTimerLock) {
          if (useTimerBasedResizing == false && resizingTimer != null)
            resizingTimer.Dispose( );
          else if (useTimerBasedResizing == true)
            resizingTimer = new Timer(new TimerCallback(ResizingTimerCallback),
              null, resizingWaitTime, Timeout.Infinite);
        }
      }
    }
  }

  private int resizingWaitTime;
  /// <summary>
  /// Gets or sets a value that indicates the time between to checks for low and
  /// high water situations. Also see UseTimerBasedResizing.
  /// </summary>
  public int ResizingWaitTime {
    get {
      return resizingWaitTime;
    }
    set {
      if (resizingWaitTime != value) {
        resizingWaitTime = value;
        lock (resizingTimerLock) {
          if (resizingTimer != null)
            resizingTimer.Change(resizingWaitTime, Timeout.Infinite);
        }
      }
    }
  }

  private int highWaterMark;
  /// <summary>
  /// Gets or sets a value indicating the percentage of used objects in the pool
  /// that must be exceeded for the pool to be grown automatically.
  /// </summary>
  public int HighWaterMark {
    get {
      return highWaterMark;
    }
    set {
      if (highWaterMark != value) {
        highWaterMark = value;
      }
    }
  }

  private int lowWaterMark;
  /// <summary>
  /// Gets or sets a value that the percentage of used objects in the pool
  /// must fall below for the pool to be shrunken automatically.
  /// </summary>
  public int LowWaterMark {
    get {
      return lowWaterMark;
    }
    set {
      if (lowWaterMark != value) {
        lowWaterMark = value;
      }
    }
  }

  private int shrinkThreshold;
  /// <summary>
  /// Gets or sets a value indicating the number of times the pool must
  /// be judged too big before it is shrunken.
  /// </summary>
  public int ShrinkThreshold {
    get {
      return shrinkThreshold;
    }
    set {
      if (shrinkThreshold != value) {
        shrinkThreshold = value;
      }
    }
  }

  private int growThreshold;
  /// <summary>
  /// Gets or sets a value indicating the number of times the pool must
  /// be judged too small before it is grown.
  /// </summary>
  public int GrowThreshold {
    get {
      return growThreshold;
    }
    set {
      if (growThreshold != value) {
        growThreshold = value;
      }
    }
  }

  Slot FindUnusedSlot( ) {
    return pool.Find(delegate(Slot slot) {
      return !slot.InUse;
    });
  }

  /// <summary>
  /// Shrinks the pool size by count elements, at most. The method removes
  /// only unused pool objects, as long as it finds them.
  /// </summary>
  public void ShrinkPoolBy(int count) {
    if (count  0 && unusedSlot != null);
    }
  }

  /// Returns the number of used objects in the pool.
  ///
  public int GetInUseCount( ) {
    int count = 0;
    pool.ForEach(delegate(Slot slot) {
      if (slot.InUse)
      count++;
    });
    return count;
  }

  /// <summary>
  /// Returns the percentage of used objects in the pool.
  /// </summary>
  public int GetFillLevel( ) {
    return GetInUseCount( ) / pool.Count * 100;
  }

  int fillLevelFoundTooLow;
  int fillLevelFoundTooHigh;

  void ResizingTimerCallback(object state) {
    int fillLevel = GetFillLevel( );

    if (fillLevel  highWaterMark) {
      fillLevelFoundTooHigh++;
      fillLevelFoundTooLow = 0;
    }
    else
      fillLevelFoundTooHigh = fillLevelFoundTooLow = 0;

    if (fillLevelFoundTooLow > shrinkThreshold) {
      ShrinkPoolBy(lowWaterMark - fillLevel);
      fillLevelFoundTooLow = 0;
    }
    else if (fillLevelFoundTooHigh > growThreshold) {
      ExtendPoolBy(fillLevel - highWaterMark);
      fillLevelFoundTooHigh = 0;
    }

    lock (resizingTimerLock)
      if (resizingTimer != null)
        resizingTimer.Change(resizingWaitTime, Timeout.Infinite);
  }

  // ...
}

This is the fifth article in my mini series about object pooling. Be sure to read part 1, part 2, part 3 and part 4 first. This part is going to make some modifications to the code in the GetObject method to implement various alternative behaviours there. Think about it: what do you want to happen if there’s no free object to be had in the pool? I came up with the following possible options:

  1. Return null. In this case, the caller would have to deal with the problem further if it can’t get a pool object.
  2. Throw an exception. Really just a variant of (1), because it also pushes the problem out to the caller.
  3. Try again. Because objects are being used and returned to the pool all the time, it might make sense just to wait a bit and try to allocate an object one more time… or two more times, even. A maximum number of tries would be good, I guess.
  4. Extend the pool. The general growing/shrinking discussion hasn’t taken place yet in these articles, but possibly the case where no more objects are available would be a good place to grow the pool.

This is the fourth article in my mini series about object pooling. Be sure to read part 1, part 2 and part 3 first. This part will be about automated object creation. To begin with, we need a way for the object pool to have additional objects created at all. One way to do that would be to just call new on the object type – and to use the new constraint on the generic class definition, of course. But that’s an unnecessary restriction, and it would imply that poolable classes always need to have a default constructor. So I decided to go a different way and just define an interface that gets passed in to the Pool class and that can be used when new objects need to be created. This is it:

public interface IObjectFactory<T> {
  T CreateObject( );
}

This is the third article in my mini series about object pooling. Be sure to read part 1 and part 2 first. In this part I’m going to put some of the infrastructure in place that’s needed to handle the list of pooled objects, to make objects available and to allow for them to be put back into the pool.

Initializing the pooled object list

This is the second article in my mini series about object pooling. You can find the first part here. Now I want to get going by defining an interface for the pool – I don’t mean a C# interface, but rather a framework for the methods and properties that the implemented class is going to have. I’ve also given some thought to the internal organization. One thing’s clear: the pool needs to have a list of objects that it currently holds. This list will have to be extendable, but there aren’t any other requirements, so a simple List<T> should do just fine. A more interesting question is, what exactly does the list store? It could just be instances of the object type we are pooling, but isn’t there management information that has to be stored as well? Like which objects are in use and which aren’t, to start with?

The Slot

The other day there was a thread in a newsgroup which ended up discussing object pooling. Jon pointed to Spring.NET – an application framework for enterprise .NET applications. I’m sure there are other implementations out there, at the moment, Spring.NET merely offers a few interfaces and a rather simplistic implementation of a pool. I thought it might be interesting to people to see how pooling functionality can be implemented, so I’m going to do that for this article, which is supposed to be a first in a small series.

What is an object pool?

In a project on which I’m currently working, I had these classes:

class MultiCriteria : Criteria {
  public MultiCriteria(params Criteria[] criteria) {
    criteriaList = new BindingList<Criteria>(criteria);
  }

  private BindingList<Criteria> criteriaList;
  public BindingList<Criteria> CriteriaList {
    get { return criteriaList; }
    set { criteriaList = value; }
  }
}

class AllCriteria : MultiCriteria {
  public AllCriteria() { }
  public AllCriteria(params Criteria[] criteria) : base(criteria) { }
}

Something I heard yesterday made me think about the aspect of performance, when deciding whether to use interfaces or delegates to implement a specific feature. For example, when implementing the Observer pattern, the classic approach involves interfaces, while .NET has support for (multicast) delegates natively, suggesting a builtin approach that might make more sense in a .NET language.

To make this decision, there are of course many arguments to consider – most importantly, when talking about design patterns, recognisability is an important factor that might be better served by following the classic approach. Nevertheless, .NET delegates and events are more flexible and easier to implement, so I figured that recognisability might not have the final word here. In some cases, the performance of the two respective approaches might not be very important. These days other aspects of software development are often more important than performance-based evaluations.

I heard criticism about my first post on the topic: if a control was on the form, apart from the background drawing, the rubber rectangle would appear behind the control, not in front of it. Of course there are several ways to change this, I decided to implement one of them just for fun 😃 This is what things look like before and after my changes:

I saw the question coming up in a newsgroup today: how do you draw a selection rubber band just like the one Explorer uses, in C#? The first thing that came to mind was the ControlPaint.DrawReversibleFrame() method, but that’s rather restricted. It’s fine to draw a rectangle around an area to select, but it can’t do anything more than that and it also has problems because it draws over windows that are supposed to be in front of the current app window. Here are screenshots of a selection made in Explorer and a selection made in my sample program. Nice, huh? 😃