Reputation: 20800
I have a class (simplified example) like :
public class SomeCollection : ICloneable
{
public void Add(Item item) { /* ... */ }
public void Remove(Item item) { /* ... */ }
public Item Get(Key key) { /* ... */ }
/*
...
*/
public object Clone() { /* ... */ }
}
I need that when a thread enters Clone() no other thread can enter in Add or Remove but can enter in Get. At first I thought of :
public void Add(Item item) { lock(addLock) { /* ... */ } }
public void Remove(Item item) { lock(removeLock) { /* ... */ } }
public object Clone(Item item)
{
lock(addLock)
{
lock(removeLock)
{
/* ... */
}
}
}
This works (I think) but has certain disadvantages : * I don't want two threads entering Add to block one another - I am dealing with that deeper in code * I will have to withstand the locking overhead for each call to Add or Remove
Then I thought of this
private volatile bool cloning = false; // notice the volatile keyword
public void Add(Item item)
{
int i = 0;
while(cloning)
{
if (i++ > 20)
throw new TimeoutException();
Thread.Sleep(50); // waits 50 milliseconds
}
/* ... */
} // and the same for Remove
public object Clone()
{
cloning = true;
try
{
/* do the cloning */
} finally { cloning = false; }
}
However this approach :
I have given ReadWriterLockSlim a short glance but doesn't seem to fit in my scenario.
I need this because the Clone method takes long time (may take over a second - the collection is HUGE) and an alteration in this time will blow up the enumerator (used in a foreach loop). Yes, I must use the foreach since the underlying key collection does not expose anything else than an IEnumerable.
What wouly you recommend?
Upvotes: 2
Views: 205
Reputation: 15782
Could you explain more why ReaderWriterLockSlim doesn't fit for your scenario?
Sure, you won't use it for it's classic use, but consider the Clone method as your writer and the add/remove methods as your readers and I think it fits.
[edit] One other thing: If you go this route, make sure you document why you're using ReaderWriterLockSlim 'backwards' so the next person who reads the code (or you in six months) understands what's going on.
Upvotes: 1