ILoggable

A place to keep my thoughts on programming

 Subscribe

geekblog
[at]
claassen [dot] net

Powered by Blogger

Friday, January 11, 2008

More Deferred Execution Fun: foreach and delegation scope

This is closely related to my last post on deferred execution gotchas and its basically more "if you inline delegated code, you may easily overlook scope side-effects". This time it's about dealing with foreach and using the local each item for deferred execution.
public void SpawnActions()
{
  foreach (ActionContext context in contexts)
  {
    int id = context.Id;
    Action<int> callback =  
      (workerNumber) =>
      {
        Console.WriteLine("{0} Id: {1}/{2}", workerNumber, id, context.Id);
      };
    ThreadPool.QueueUserWorkItem(new WaitCallback(FutureExecute), callback);
  }
}

public void FutureExecute(object state)
{
  int id = worker++;
  Action<int> callback = state as Action<int>;
  Thread.Sleep(500);
  callback(id);
}

The output looks like this:

0 Id: 0/9
1 Id: 1/9
2 Id: 2/9
3 Id: 3/9
4 Id: 4/9
5 Id: 5/9
6 Id: 6/9
7 Id: 7/9
8 Id: 8/9
9 Id: 9/9
So while the foreach scope variable context is kept alive for the deferred execution, it turns out that foreach re-uses the variable on each pass through the loop and therefore when the Action is later executed, each one has a reference to the last context. So what we need to do is create a true local variable for context so that the lambda's scope can hold on to the reference we want.
  foreach (ActionContext context in contexts)
  {
    int id = context.Id;
    // locally scoped variable
    ActionContext c2 = context;
    Action<int> callback =  
      (workerNumber) =>
      {
        Console.WriteLine("{0} Id: {1}/{2}", workerNumber, id, c2.Id);
      };
    ThreadPool.QueueUserWorkItem(new WaitCallback(FutureExecute), callback);
  }

And now our results are a bit more what we expected:

0 Id: 0/0
1 Id: 1/1
2 Id: 2/2
3 Id: 3/3
4 Id: 4/4
5 Id: 5/5
6 Id: 6/6
7 Id: 7/7
8 Id: 8/8
9 Id: 9/9

Labels: , , , ,

Sunday, December 30, 2007

The dangers of deferred execution

I recently wrote about Action & Func, which along with Lambda expression let you do easy inline callbacks like this:
Utility.ActionDownloader.Download(
  Configuration.GetAssetUri(dto.Url),
  (Downloader d) =>
  {
    FloatContainer c = (FloatContainer)XamlReader.Load(d.ResponseText);
    c.Initialize(dto);
  });
i.e. I can call a downloader and inline pass it a bit of code to execute once the download completes. But the catch of course is that looking at the code, and following the usual visual tracing of flow hides the fact that c.Initialize(dto) doesn't get called until some asynchronous time in the future. Now, that's always been a side-effect of delegates, but until they became anonymous and inline, the visual deception of code that looks like it's in the current flow scope but isn't wasn't there.

What happened was that I needed my main routine to execute some code after FloatContainer was initialized, and by habit i created an Initialized event on FloatContainer. Of course this was superfluous, since my lambda expression called the synchronous Initialize, i.e my action could be placed inline after that call to c.Initialize(dto) and be guaranteed to be called after initialization had completed.

This scenario just meant I created some superfluous code. However, I'm sure as I use lambda expression more, there will be more pitfalls of writing code that doesn't consider that its execution time is unknown, as is the state of the objects tied to the scope of the expression.

This last bit about objects tied to the expression scope is especially tricky and I think we will see some help in terms of Immutable concepts weaving their way into C# 3.x or 4.0, as the whole functional aspect of lambda expressions really work best when dealing with objects that cannot change state. Eric Lippert's been laying the groundwork in a number of posts on the subject and while he constantly disclaims that his ponderings are not a roadmap for C#, I am still going to assume that his interest and recognition of the subject of Immutables will have some impact in a future revision of the language. Well, I at least hope it does.

Labels: , , ,

Thursday, December 13, 2007

Action & Func: Never write another delegate

With lambda expressions in C#, the Func generic delegate and it's variations have been getting a lot of attention. So naturally, you might think that the lambda syntax is just a shortcut for creating anonymous delegates, whether they return values or not.

First let's look at the evolution of delegates from 1.1 to now. Delegates, simply are the method equivalent of function pointers. They let you pass a method call as an argument for later execution. The cool thing (and a garbage collection pitfall) is that a delegate creates a lexical closure, i.e. the delegate carries with it the object that the method gets called on. For garbage collection this means that a delegate prevents an object from being collection. That's why it's important to unsubscribe from those events you subscribed to.

But I digress. Let's define a delegate that returns an Integer and a method that matches that delegate:

delegate int IntProducerDelegate();

public int x = 0;
public int IntProducer()
{
  return x++;
}

With the original .NET 1.0 syntax we'd create the delegate like this:

IntProducerDelegate p1 = new IntProducerDelegate(IntProducer);

Now we can call p1() and get an integer back, and since it's closure, each time we call p1() the originating objects x increases as does our return value.

Then, in .Net 2.0 we got anonymous delegates.

IntProducerDelegate p2 = delegate { return IntProducer(); };

// or with IntProducer's action inlined...
IntProducerDelegate p3 = delegate { return x++; };

This got rid of the need to create a method just to pass along a closure that manipulated our object at a later time. The other thing that anonymous delegates re-inforce is that delegates just care about signature. IntProducerDelegate can get assigned any delegate that takes no argument and returns an int. That sounds like a perfect scenario for a delegate and in .NET 3.5, we got just that, a set of generic delegates called Func. Using Func, we quickly get to our lambda expression replacing the original delegate syntax like this:

// create a new Func delegate just like the IntProducerDelegate
IntProducerDelegate p3 = new Func<int>(IntProducer);

// which means that we don't need IntProducerDelegate at all anymore
Func<int> p4 = delegate { return x++; };

// and the anonymous delegate can also be shorthanded with a lambda expression
Func<int> p5 = () => { return x++; };
// which says, given that we take no argument "()", execute and return the following "return x++;"

However, before there ever was Func, .Net 2.0 introduced the generic delegate Action, which is a natural counterpart to Func, encapsulating a method that does not return anything. Following through the example of the producer, we'll create a consumer like:

delegate void IntConsumerDelegate(int i);

public void IntConsumer(int i)
{
  Console.WriteLine("The number is {0}", i);
}

Now following the same evolution of syntax we get this:

IntConsumerDelegate c1 = new IntConsumerDelegate(IntConsumer);

IntConsumerDelegate c2 = new Action<int>(IntConsumer);

Action<int> c3 = delegate(int i) { Console.WriteLine("The number is {0}", i); };

Action<int> c4 = (i) => { Console.WriteLine("The number is {0}", i); };

So lambda syntax can be used to create either a Func or an Action. And that also means that we never have to explicitly need to create another delegate, being able to use a variation of these two generic delegates as our arsenal for storing lambda expressions of all kinds.

Labels: , , ,

Sunday, April 08, 2007

Are delegates the reason we have C#?

This may be ancient news, but I just came across an article that strongly implied that the reason .NET came about was because Sun didn't like Microsoft's addition of delegates to J++. That surely is a condensation of events, but it's certainly an interesting yarn.

I got into this whole subject because I needed an object to subscribe to the state change of another object in my java project. And I didn't want to create a tight coupling between otherwise unrelated objects. In C#, I would have created an event for the state change and have the second object subscribe to it. Done.

Alas, I'm in java and don't have delegates, e.g. no events in the way i'm used to. I remembered dealing with creating lots of anonymous inner classes during some long ago experiences with swing programming, which I always found to be less than transparent in presentation. So I figured I'd do some digging to see how delegation and events should be handled in java. I don't like seeing getFoo()/setFoo() from someone not used to C# properties, and I don't want to subject someone else to my C#-ing of java code in return.

I started googling java, delegates and inner classes and came across a plethora of interesting articles, including the obligatory C# is better better than java because it has delegates and java kicks C#'s ass because isn't littered with atrocious syntactic sugar like delegates when inner classes will do variety. Of these, the most entertaining was a rather testy condemnation of delegates in J++ in the form of a white paper on Sun's site. Considering the stance Sun has taken over the years on java, i.e. binding the language, runtime and philosophy into a single indivisible unit, having MS try subvert the language with what to many looks like a procedural programming throwback certainly could have been a significant motivator for the lawsuit that revoked Microsoft's java license. Looking at C# and the CLR, Microsoft obviously saw a lot of things it liked in the java language and the jvm. So the result that .NET came about because Sun rejected delegates doesn't seem too far fetched and my favorite version of the story so far.

Now, back to the problem at hand, how does one do delegation in java and the answer does appear to be with inner classes functioning as callbacks. This certainly does the trick. But that's a bunch of code and interfaces to create which in the end doesn't improve the readability of the code. As an illustration, here is the C# code and the java code I created to get the same effect. Note: I didn't need the extra information that C# events provide, i.e. the event source and event arguments, so I left them out of the java version to keep the code more concise. I also didn't do any checking if there are subscribers, etc -- read: this is an illustration not production code :)

Publisher

// C# Publisher
public class Publisher
{
  // create the event, which implicitly gives us add/delete subscribers
  public event EventHandler someAction;

  public void DoAction()
  {
    Console.WriteLine("Start action");
    //implictly call all subscribers
    someAction(this, EventArgs.Empty);
    Console.WriteLine("End action");
  }
}
// java Publisher
public class Publisher {

    private List<EventHandler> subscribers = new ArrayList<EventHandler>();
    
    public void subscribeToAction(EventHandler notifier)
    {
        subscribers.add(notifier);
    }
    
    public void doAction()
    {
        System.out.println("Start action");
        for( EventHandler subscriber : subscribers ) {
            subscriber.handle(this);
        }
        System.out.println("End action");
    }
}

Subscriber

//C# Subscriber
public class Subscriber
{
  private string name;

  public Subscriber(string name)
  {
    this.name = name;
  }

  public void AttachToPublisher(Publisher publisher)
  {
    // subscribe to the event. This creates a closure for this particular
    // instance of Subscriber.
    publisher.someAction += new EventHandler(RespondToAction);
  }

  void RespondToAction(object sender, EventArgs e)
  {
    Console.WriteLine("Responding to action for '" + name + "'");
  }
}
// java Subscriber
public class Subscriber {

    private String name;
    
    public Subscriber(String name) {
        this.name = name;
    }
    
    public void attachToPublisher(Publisher publisher) {
        // create a new anonymouse instance of the EventHandler
        // as a closure for this instance of Subscriber
        publisher.subscribeToAction(new EventHandler() {
            public void handle(Publisher publisher) {
                respondToAction();
            }
        }
        );
        
    }
    
    private void respondToAction() {
        System.out.println("Responding to action for '" + name + "'");
    }
}

EventHandler

In C# this is just built in plumbing. In java we create a simple interface that our anonymous inner class will implement:
public interface EventHandler {
    void handle(Publisher publisher);
}

Now we exercise the code:

      Publisher p = new Publisher();
      Subscriber s1 = new Subscriber("abc");
      Subscriber s2 = new Subscriber("xyz");
      s1.AttachToPublisher(p);
      s2.AttachToPublisher(p);
      p.DoAction();

The java code is virtually identical just with different casing for code style and both produce this output:

Start action
Responding to action for 'abc'
Responding to action for 'xyz'
End action
Now add lost of different events and unsubscribing of events, plus more complex EventHandlers and the amount of code you end up writing quickly becomes significant. If there is one thing object oriented programming encourages us to do is to take repetitive code patterns and formulate reusable objects. Plenty of people in the java community have created delegate-like helpers that make delegation easier to read and maintain than simple inner classes, my favorite so far being Alex Winston's strongly typed approach.

So are delegates just syntactic sugar or a throw-back to procedural coding? For those with only a cursory understanding of delegates, they do just look like function pointers, like C, or at best, type-safe function pointers. But just like inner classes they create instance specific closures, plus they throw in functionality for handling multi-casting and handling synchronous and asynchronous invocation of the closure. I, at least, think delegates as a first-class citizen of the runtime make life easier, improve readability and do not detract from the object oriented nature of the surrounding code.

Labels: , , , , ,