Skip to content

Instantly share code, notes, and snippets.

@andreabalducci
Created July 5, 2011 21:05
Show Gist options
  • Save andreabalducci/1065939 to your computer and use it in GitHub Desktop.
Save andreabalducci/1065939 to your computer and use it in GitHub Desktop.
First Attempt to create a Dynamic Object with Thread Safe support (and first time dynamic too ;D)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using NUnit.Framework;
using Prxm.ManPack.Monitor;
using SharpTestsEx;
namespace Prxm.ManPack.ServicesTests.MonitorTests
{
[TestFixture]
public class MonitorResourceTest
{
[Test]
public void CanSetMissingPropertyValue()
{
dynamic resouceData = new ResourceData();
resouceData.MyValue = 10;
Assert.AreEqual(10, resouceData.MyValue);
}
[Test]
public void CanSetPropertyWithinLock()
{
dynamic resouceData = new ResourceData();
using (resouceData.Lock())
{
resouceData.MySecondValue = "Test";
}
Assert.AreEqual("Test", resouceData.MySecondValue);
}
[Test]
public void Counter_without_lock_is_not_thread_safe()
{
dynamic resouceData = new ResourceData();
var resetEvent = new ManualResetEvent(false);
resouceData.Counter = 0;
var list = new List<Thread>();
for (int c = 0; c < 10; c++)
{
Thread t = new Thread(state =>
{
resetEvent.WaitOne();
var counter = resouceData.Counter;
Thread.Sleep(10);
resouceData.Counter = counter + 1;
}
);
list.Add(t);
}
list.ForEach(x => x.Start());
resetEvent.Set();
list.ForEach(x => x.Join());
int counterValue = resouceData.Counter;
counterValue.Should().Be.LessThan(10);
}
[Test]
public void Counter_inside_lock_is_thread_safe()
{
dynamic resouceData = new ResourceData();
resouceData.Counter = 0;
var list = new List<Thread>();
var resetEvent = new ManualResetEvent(false);
for (int c = 0; c < 10; c++)
{
Thread t = new Thread(state =>
{
resetEvent.WaitOne();
using (resouceData.Lock())
{
var counter = resouceData.Counter;
Thread.Sleep(10);
resouceData.Counter = counter + 1;
}
});
list.Add(t);
}
list.ForEach(x => x.Start());
resetEvent.Set();
list.ForEach(x => x.Join());
int counterValue = resouceData.Counter;
counterValue.Should().Be.EqualTo(10);
}
}
}
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
namespace Prxm.ManPack.Monitor
{
public class ResourceData : DynamicObject
{
private readonly object _syncRoot = new object();
private readonly Dictionary<string, object> _values = new Dictionary<string, object>();
private class LockHandler : IDisposable
{
private readonly object _syncRoot;
public LockHandler(object syncroot)
{
_syncRoot = syncroot;
System.Threading.Monitor.Enter(_syncRoot);
}
public void Dispose()
{
System.Threading.Monitor.Exit(_syncRoot);
}
}
public IDisposable Lock()
{
return new LockHandler(_syncRoot);
}
public ResourceData()
{
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_values[binder.Name] = value;
return true;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return _values.TryGetValue(binder.Name, out result);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment