Record write-once initialization and report whether later reads were locked out.

write-once value A coordination report can record write-once initialization. A `Lazy<int>` runs its build function the first time the value is read and caches the result, so later reads are served from the cached value and never build again. The build count stays at one however many times the value is read. The status line summarizes whether the slot stayed unset, was set by a single read, or stayed locked at one build while later reads were served.

Lazy Init Coordination Report

reads
LazyInitCoordinationReport.cs
Replay: real traced execution (multi-file project)
using System;

class Program
{
    static int builds = 0;

    static int Build()
    {
        builds++;
        return 7;
    }

    static void Main()
    {
        int reads = 1;
        var slot = new Lazy<int>(Build);
        int served = 0;

        for (int i = 0; i < reads; i++)
        {
            int value = slot.Value;
            served++;
        }

        bool created = slot.IsValueCreated;

        string status;
        if (!created)
        {
            status = "unset";
        }
        else if (served <= 1)
        {
            status = "set";
        }
        else
        {
            status = "locked";
        }

        Console.WriteLine("reads=" + reads + " served=" + served + " builds=" + builds + " " + status);
    }
}
using System;

class Program
{
    static int builds = 0;

    static int Build()
    {
        builds++;
        return 7;
    }

    static void Main()
    {
        int reads = 0;
        var slot = new Lazy<int>(Build);
        int served = 0;

        for (int i = 0; i < reads; i++)
        {
            int value = slot.Value;
            served++;
        }

        bool created = slot.IsValueCreated;

        string status;
        if (!created)
        {
            status = "unset";
        }
        else if (served <= 1)
        {
            status = "set";
        }
        else
        {
            status = "locked";
        }

        Console.WriteLine("reads=" + reads + " served=" + served + " builds=" + builds + " " + status);
    }
}
using System;

class Program
{
    static int builds = 0;

    static int Build()
    {
        builds++;
        return 7;
    }

    static void Main()
    {
        int reads = 2;
        var slot = new Lazy<int>(Build);
        int served = 0;

        for (int i = 0; i < reads; i++)
        {
            int value = slot.Value;
            served++;
        }

        bool created = slot.IsValueCreated;

        string status;
        if (!created)
        {
            status = "unset";
        }
        else if (served <= 1)
        {
            status = "set";
        }
        else
        {
            status = "locked";
        }

        Console.WriteLine("reads=" + reads + " served=" + served + " builds=" + builds + " " + status);
    }
}
  1. reads ← 1, slot ← Value is not created., served ← 0

    13static void Main()14{15    int reads→ 1 = 1; //@reads=0, 216    var slot→ Value is not created. = new Lazy<int>(Build);17    int served→ 0 = 0;
  2. for (int i = 0; i < reads; i++)

    19for (int i0 = 0; i < reads1; i++)20{21    int value = slot.Value;
  3. builds ← 1

    7static int Build()8{9    builds→ 1++;10    return 7;11}
  4. value ← 7, served ← 1

    20{21    int value→ 7 = slot.Value7;22    served→ 1++;23}
  5. created ← True

    25bool created→ True = slot.IsValueCreatedTrue;2627string status;28if (!created)
  6. status ← set

    31}32else if (served1 <= 1)33{34    status→ set = "set";35}
  7. Console.WriteLine("reads=" + reads + " served=" + served + " builds=" …

    41    Console.WriteLine("reads=" + reads1 + " served=" + served1 + " builds=" + builds1 + " " + statusset);42}
    outputreads=1 served=1 builds=1 set
  1. reads ← 0, slot ← Value is not created., served ← 0, created ← False

    13static void Main()14{15    int reads→ 0 = 0;16    var slot→ Value is not created. = new Lazy<int>(Build);17    int served→ 0 = 0;1819    for (int i = 0; i < reads; i++)20    {21        int value = slot.Value;22        served++;23    }2425    bool created→ False = slot.IsValueCreatedFalse;2627    string status;28    if (!created)
  2. status ← unset

    27string status;28if (!createdFalse)29{30    status→ unset = "unset";31}
  3. Console.WriteLine("reads=" + reads + " served=" + served + " builds=" …

    41    Console.WriteLine("reads=" + reads0 + " served=" + served0 + " builds=" + builds0 + " " + statusunset);42}
    outputreads=0 served=0 builds=0 unset
  1. reads ← 2, slot ← Value is not created., served ← 0

    13static void Main()14{15    int reads→ 2 = 2;16    var slot→ Value is not created. = new Lazy<int>(Build);17    int served→ 0 = 0;
  2. for (int i = 0; i < reads; i++)

    pass 1 of 2
    19for (int i0 = 0; i < reads2; i++)20{21    int value = slot.Value;
  3. builds ← 1

    7static int Build()8{9    builds→ 1++;10    return 7;11}
  4. value ← 7, served ← 1

    20{21    int value→ 7 = slot.Value7;22    served→ 1++;23}
  5. value ← 7, served ← 2

    pass 2 of 2
    19for (int i1 = 0; i < reads2; i++)20{21    int value→ 7 = slot.Value7;22    served→ 2++;23}
  6. created ← True

    25bool created→ True = slot.IsValueCreatedTrue;2627string status;28if (!created)
  7. status ← locked

    35}36else37{38    status→ locked = "locked";39}
  8. Console.WriteLine("reads=" + reads + " served=" + served + " builds=" …

    41    Console.WriteLine("reads=" + reads2 + " served=" + served2 + " builds=" + builds1 + " " + statuslocked);42}
    outputreads=2 served=2 builds=1 locked