0

For my project I am trying to create a single global store to serve a mutable state like this:

  // Immutable program state
  sealed public class State : IEquatable<State> {
    public State(ClientsConnections clientsConnections, ImmutableList<string> ids) {
      this.ClientsConnections = clientsConnections;
      this.Ids = ids;
    }

    public readonly ClientsConnections ClientsConnections; // ClientsConnections is immutable
    public readonly ImmutableList<string> Ids; // also immutable

    public override int GetHashCode() => HashCode.Combine(AgentsConnections.GetHashCode(), Ids.GetHashCode());
    public override bool Equals(object obj) { var o = obj as State; return o is null ? false : ClientsConnections.Equals(o.ClientsConnections) && Ids.Equals(Ids); }
    public bool Equals(State o) => object.Equals(this, o); 
    public static bool operator ==(State o1, State o2) => object.Equals(o1, o2); 
    public static bool operator !=(State o1, State o2) => !object.Equals(o1, o2);
  }

  // Store is a mutable singleton
  sealed public class Store {
    readonly object stateLock = new object();

    public Store() => this.State = new State(new ClientsConnections(), ImmutableList<string>.Empty);

    public State State { get; private set; }
    public void SetState(Func<State, State> f) { lock (stateLock) State = f(State); }
  }

I then use it in the code like this:

Thread1 - f1() { 
  var currState=Store.State; 
  log(currState.ids);
}

Thread2 - f2() { 
  Store.SetState(currState => {
    var newids = currState.Ids.Add("hello");
    return new State(currState.ClientsConnections, newids);
  });
}

Questions:

  1. Is this code thread safe ? in particular do I need to lock the Store.State getter ? my reasoning is since the getter does an atomic assignment copying the state reference by value then I do not need to lock it here ?

  2. Can I/should I use ImmutableInterlocked here ?

kofifus
  • 17,260
  • 17
  • 99
  • 173
  • `Can I/should I use ImmutableInterlocked here ?` I would say Yes. What are your concerns with using it? https://msdn.microsoft.com/en-us/library/mt806088(v=vs.111).aspx is the method you likely want to use. – mjwills Aug 16 '18 at 23:17
  • I'm not sure how to pass f in this case – kofifus Aug 16 '18 at 23:18
  • 1
    if you are using immutable lists for thread safety, you might be heading down the wrong path and there maybe be more appropriate thread safe structures. However it really depends on your use case. maybe if you can explain the basics of it in your question – TheGeneral Aug 16 '18 at 23:27
  • again, Immutable list is just an example here, I am trying to capture the pattern of an immutable state containing many different immutable objects that is read/write via a singleton store – kofifus Aug 16 '18 at 23:28
  • If `State` is immutable, would this ever return true: `public bool Equals(State o) => object.Equals(this, o);` Seems like the state equality logic should go here, and then the object equality method should call this one by `return Equals(obj as State);` – Rufus L Aug 16 '18 at 23:45
  • Rufus, yes it will call Equals(object obj) .. see https://stackoverflow.com/a/51130223/460084 – kofifus Aug 17 '18 at 01:29

1 Answers1

0

Is this code thread safe ? in particular do I need to lock the Store.State getter ? my reasoning is since the getter does an atomic assignment copying the state reference by value then I do not need to lock it here ?

As long as you are happy with stale data, yes it will work fine.

Can I/should I use ImmutableInterlocked here ?

Yes, I think you should (but you should profile to confirm whether it actually provides a benefit). ImmutableInterlocked.Update is what I would suggest.

mjwills
  • 23,389
  • 6
  • 40
  • 63