Bad Memories – Episode 2 (exceptions with a vengeance)

Refresher…

In the last post I enhanced my .Memoize() extension so that it supported exceptions. It now caches resulting exceptions and re-throws them for subsequent callers  however there is still a problem.

public static Func<T> Memoize<T>(this Func<T> f)
{
    var gate = new object();
    var set = false;
    T result = default(T);
    Exception error = null;
    return () =>
    {
        if (!set)
        {
            lock (gate)
            {
                if (!set)
                {
                    try
                    {
                        result = f();
                    }
                    catch(Exception ex)
                    {
                        error = ex;
                    }

                    set = true;
                }
            }
        }
        if(error != null) throw error;
        return result;
    };
}

The function produced by .Memoize() is supposed to be thread safe (hence the locking). Looking closely though, multiple threads could be throwing the same exception object at the same time! You need to be careful with exceptions as they are mutable objects and throwing them tells the CLR to record stack trace information as it bubbles up the call stack. This could result in exceptions being logged with a corrupt stack trace, making it difficult to debug application errors. Take a look at the following example.

static void MethodA(Exception ex)
{
    throw ex;
}

static void MethodB(Exception ex)
{
    throw ex;
}

static void Main()
{
    // exception that we are going to throw multiple times
    var test = new Exception("testing");

    // schedule execution of method A
    Scheduler.NewThread.Schedule(() =>
    {
        try { MethodA(test); }
        catch (Exception ex)
        { // thread sleep is here to allow other method time to also throw the exception
            Thread.Sleep(10);
            Console.WriteLine("Error from MethodA: " + ex.ToString());
        }
    });

    // schedule execution of method B
    Scheduler.NewThread.Schedule(() =>
    {
        try { MethodB(test); }
        catch (Exception ex)
        {
            Thread.Sleep(10);
            Console.WriteLine("Error from MethodB: " + ex.ToString());
        }
    });

    Console.ReadLine();
}

The output will vary but when I ran it, it looked like this;

Error from MethodB: System.Exception: testing
   at Program.MethodB(Exception ex) in *snip*

Error from MethodA: System.Exception: testing
   at Program.MethodB(Exception ex) in *snip*

“That’s weird. How come an exception thrown from MethodA has MethodB in it’s stack trace?”

The solution is to simply wrap the original exception in a new exception each time it’s thrown. This ensures each caller will get a clean stack trace. Here is an updated version.

public class MemoizeException : Exception
{
    public MemoizeException(Exception innerException)
        : base("see inner exception", innerException) { }
}

public static Func<T> Memoize<T>(this Func<T> f)
{
    var gate = new object();
    var set = false;
    T result = default(T);
    Exception error = null;
    return () =>
    {
        if (!set)
        {
            lock (gate)
            {
                if (!set)
                {
                    try
                    {
                        result = f();
                    }
                    catch (Exception ex)
                    {
                        error = ex;
                    }
                    set = true;
                }
            }
        }
        if (error != null) throw new MemoizeException(error);
        return result;
    };
}

That’s it for now – don’t worry more excitement coming soon!

James

Bad Memories – Episode 1

I’ve discussed memoization a few times. Here is the implementation I used last time.

public static Func<T> Memoize<T>(this Func<T> f)
{
    var gate = new object();
    var set = false;
    T result = default(T);
    return () =>
    {
        if (!set)
        {
            lock (gate)
            {
                if (!set)
                {
                    result = f();
                    set = true;
                }
            }
        }
        return result;
    };
}

Strictly speaking though there is a bit of a problem. Consider the following;

Func<int> f = () =>
{
    "I’m making side effects".Dump();
    throw new Exception("42");
};

var memoizef = f.Memoize();
try{ memoizef(); } catch{}
try{ memoizef(); } catch{}

OUTPUT

I’m making side effects
I’m making side effects

In the case of exceptions, we are reproducing the side effects of the underlying function. Here is a tweaked implementation that handles exceptions. There is however an interesting problem with it. Can you spot it?

public static Func<T> Memoize<T>(this Func<T> f)
{
    var gate = new object();
    var set = false;
    T result = default(T);
    Exception error = null;
    return () =>
    {
        if (!set)
        {
            lock (gate)
            {
                if (!set)
                {
                    try
                    {
                        result = f();
                    }
                    catch(Exception ex)
                    {
                        error = ex;
                    }

                    set = true;
                }
            }
        }
        if(error != null) throw error;
        return result;
    };
}

More soon,
James

Posted in .NET, C#. 2 Comments »

Filtering by information in previous elements

I’ve been off work sick for the last 2 days so I thought I’d catch up on some blogging. It’s been a couple of weeks as I’ve been busy reading the Haskell language specification. There is obviously a close relationship between F# and Haskell, but its becoming increasing clear to me that many of the C# 2.0 & 3.0 language features were inspired by Haskell (Erik Meijer’s influence I suppose) & its predecessors.

I’ll have some posts on what I’m learning shortly, but for now, back to LINQ!

So we have a stream of notifications, some of which are related to each other.

new[]
{
    new { Id = 42, Parent = 0 },
    new { Id = 100, Parent = 38 },
    new { Id = 101, Parent = 42 },
    new { Id = 102, Parent = 37 },
    new { Id = 103, Parent = 101 },
    new { Id = 104, Parent = 85 },
    new { Id = 105, Parent = 95 },
    new { Id = 106, Parent = 103 },
}

The desired output is;

42
101
103
106

I’ve found you can easily do this in Rx by combining Scan & DistinctUntilChanged.

new[]
{
    new { Id = 42, Parent = 0 },
    new { Id = 100, Parent = 38 },
    new { Id = 101, Parent = 42 },
    new { Id = 102, Parent = 37 },
    new { Id = 103, Parent = 101 },
    new { Id = 104, Parent = 85 },
    new { Id = 105, Parent = 95 },
    new { Id = 106, Parent = 103 },
}
.ToObservable()
.Scan(0, (acc, item) => item.Parent == acc ? item.Id : acc)
.DistinctUntilChanged()

Unfortunately the Enumerable extensions are missing DistinctUntilChanged. I’ll ask if it can be added to the next release.

Cheers,
James

 

 

Follow

Get every new post delivered to your Inbox.