Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to handle many concurrently interacting entities in C#
    primarykey
    data
    text
    <p>I am developing an application that has many different entities that can interact concurrently. I'm wondering what the best way is for those entities to interact with each other in a thread safe way.</p> <p>To demonstrate with some simplified code, consider that each entity has it's own fiber and some state:</p> <pre><code>class Fiber { private ActionBlock&lt;Action&gt; _workQueue; public Fiber() { _workQueue = new ActionBlock&lt;Action&gt;((a) =&gt; a()); } public void Enqueue(Action a) { _workQueue.Post(a); } public void Stop() { _workQueue.Complete(); } } class EntityState { public int x { get; set; } } class Entity { private Fiber _fiber = new Fiber(); public EntityState State { get; set; } // ... } </code></pre> <p>Assume actions are arbitrarily enqueued onto an entities fiber. One such action may be that an entity must modify another entity's state. There are two options I've considered to do this in a thread safe way.</p> <p>Option 1: Only allow state mutation through a thread-safe wrapper, I.E.</p> <pre><code>class Entity { private Fiber _fiber = new Fiber(); private ReaderWriterLockSlim _stateLock = new ReaderWriterLockSlim(); private EntityState _state = new EntityState(); public T ReadState&lt;T&gt;(Func&lt;EntityState, T&gt; reader) { T result = default(T); _stateLock.EnterReadLock(); result = reader(_state); _stateLock.ExitReadLock(); return result; } public void WriteState(Action&lt;EntityState&gt; writer) { _stateLock.EnterWriteLock(); writer(_state); _stateLock.ExitWriteLock(); } // ... } </code></pre> <p>Option 2: Only allow state mutation by scheduling it onto the owning entity's fiber and return a Future so that the mutator can see when the mutation has taken place, I.E.</p> <pre><code>class Future&lt;T&gt; { public T Value { get; set; } } class Entity { private Fiber _fiber = new Fiber(); private EntityState _state = new EntityState(); public Future&lt;T&gt; AccessState&lt;T&gt;(Func&lt;EntityState, T&gt; accessor) { Future&lt;T&gt; future = new Future&lt;T&gt;(); _fiber.Enqueue(() =&gt; future.Value = accessor(_state)); return future; } // ... } </code></pre> <p>What other options haven't I considered? Is there a good way to do this? Should I be doing this at all?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload