I have cleaned and shortened a snippet of my code for a multiuser game to show what I would like to accomplish. So here it is:
public class Subject {
public List<IObject> Objects = new List<IObject>();
}
public interface IOpenable
{
void Open(Subject by, params string[] p);
void Close(Subject by, params string[] p);
bool IsOpen { get; }
}
public interface IObject {
void Pickup(Subject by, params string[] p);
void Drop(Subject by, params string[] p);
}
public class Box : IObject, IOpenable
{
bool opened = false;
Subject owner = null;
public void Pickup(Subject subject, params string[] p) {
subject.Objects.Add(this);
this.owner = subject;
}
public void Drop(Subject subject, params string[] p)
{
subject.Objects.Remove(this);
this.owner = null;
}
public void Open(Subject by, params string[] p)
{
this.opened = true;
}
public void Close(Subject by, params string[] p)
{
this.opened = false;
}
public bool IsOpen { get { return opened; } }
}
What I would like to know is:
How to prevent some user (executing code from another thread) to open a Box that is currently being Picked up by some other user.
I’ve thought of some ways but I think that people here often come up with clever ideas, that could make me avoid some stupid design issue.
EDIT: As suggested in the answers, to use the lock keyword in the open method: this is not exactly what I want, I’ll try to explain with what is allowed and what not:
The network requests we get as input are somehow async and get out of order if issued fast.
- (1) User 1 issues command PICKUP BOX
- (2) User 1 issues command OPEN BOX
- (3) User 1 issues command CLOSE BOX
- (4) User 2 issues command OPEN BOX
- (5) User 2 issues command LOOK BOX
- (6) User 1 issues command OPEN BOX
We get this order:
2,3,1,5,4,6
2 - allow
3 - allow
1 - allow [remains in execution and has not set the owner]
5(comes in between 1) - allow
4(comes in between 1) - disallow (not because already open but because 1 is in execution)
6(comes in between 1) - allow since it is from user 1, and he is currently picking it up
Thanks!
My solution to this is:
Similar to lock but not blocking.
So we lock an object when a user start picking it up,
and when Opening the box do a check that says: