Carl Rosenberger wrote:
> However, since I use my Wait() and Pulse() calls
> in the middle of a lock() block, this looks like
> I will need to completely implement my own locking
> system for CF.
That's what I did in the meanwhile.
Below is what I have come up with so far.
Should anyone see a quirk in my approach, I would be
grateful for comments. The code runs O.K. with the
test cases I used but it hasn't been tested
thoroughly yet.
Feel free to use the code for your own Wait()/Pulse()
system on CF.
// Something to be run in the lock block.
// This could be a delegate also.
// We are staying compatible to Java.
public interface Closure4 {
Object run();
}
// This is the trivial default implementation
// to be run on regular .NET, to be used as
// a reference for testing.
using System.Threading;
public class Lock4 {
public Object run(Closure4 closure) {
lock (this) {
return closure.run();
}
}
public void snooze(long timeout) {
Monitor.Wait(this, (int)timeout);
}
public void awake() {
Monitor.Pulse(this);
}
}
// Here ist our CF version. For us it's O.K., if
// the timeout value is ignored.
using System.Threading;
public class Lock4 {
private volatile Thread lockedByThread;
private volatile Thread waitReleased;
private volatile Thread closureReleased;
AutoResetEvent waitEvent = new AutoResetEvent(false);
AutoResetEvent closureEvent = new AutoResetEvent(false);
public Object run(Closure4 closure4) {
enterClosure();
Object ret;
try{
ret = closure4.run();
}catch(Exception e){
awakeClosure();
throw e;
}
awakeClosure();
return ret;
}
public void snooze(long l) {
awakeClosure();
waitWait();
enterClosure();
}
public void awake() {
awakeWait();
}
private void awakeWait() {
lock(this){
waitReleased = Thread.CurrentThread;
waitEvent.Set();
Thread.Sleep(0);
if(waitReleased == Thread.CurrentThread){
waitEvent.Reset();
}
}
}
private void awakeClosure() {
lock(this){
removeLock();
closureReleased = Thread.CurrentThread;
closureEvent.Set();
Thread.Sleep(0);
if(closureReleased == Thread.CurrentThread){
closureEvent.Reset();
}
}
}
private void waitWait(){
waitEvent.WaitOne();
waitReleased = Thread.CurrentThread;
}
private void waitClosure(){
closureEvent.WaitOne();
closureReleased = Thread.CurrentThread;
}
private void enterClosure(){
while(lockedByThread != Thread.CurrentThread){
while(! setLock()){
waitClosure();
}
}
}
private bool setLock(){
lock(this){
if(lockedByThread == null){
lockedByThread = Thread.CurrentThread;
return true;
}
return false;
}
}
private void removeLock(){
lock(this){
if(lockedByThread == Thread.CurrentThread){
lockedByThread = null;
}
}
}
}
Thanks for any hints on how to improve the above.
Kind regards,
Carl
--
Carl Rosenberger
db4o - database for objects -
http://www.db4o.com