Permalink
Browse files

Incorporated changes suggested by Phil Trelford in code review. Thank…

…s, Phil!
  • Loading branch information...
1 parent 7cab6e3 commit c71f564079c81dc83d570dff58d298ba5c58c8d3 @xoltar committed Nov 5, 2012
Showing with 56 additions and 51 deletions.
  1. +41 −39 Xoltar.Core/TransactionLock.fs
  2. +15 −12 Xoltar.Core/TransactionalDictionary.fs
View
80 Xoltar.Core/TransactionLock.fs
@@ -7,42 +7,44 @@ open System.Threading
type TransactionLock() =
let pending = LinkedList<Transaction*ManualResetEvent>()
let mutable owner : Transaction = null
- let sync = new obj()
- with
- member this.Owner
- with get () = lock sync (fun () -> owner)
- and set v = lock sync (fun () -> owner <- v)
- member this.Locked with get () = this.Owner <> null
- member this.Lock(transaction) =
- Monitor.Enter sync
- if this.Owner = null then
- if transaction <> null then
- this.Owner <- transaction
- Monitor.Exit sync
- else
- if transaction = this.Owner then
- Monitor.Exit sync
- else
- let manualEvent = new ManualResetEvent(false)
- let pair = (transaction,manualEvent)
- pending.AddLast pair |> ignore
- if transaction <> null then
- transaction.TransactionCompleted.Add (fun e ->
- lock sync (fun() -> pending.Remove(pair)) |> ignore
- lock manualEvent (fun() -> if not manualEvent.SafeWaitHandle.IsClosed then
- manualEvent.Set() |> ignore))
- Monitor.Exit sync
- manualEvent.WaitOne() |> ignore
- lock(manualEvent) manualEvent.Close
- member this.Unlock () =
- lock(sync) (fun () ->
- this.Owner <- null
- let mutable node : LinkedListNode<Transaction*ManualResetEvent> = null
- if pending.Count > 0 then
- node <- pending.First
- pending.RemoveFirst()
- if node <> null then
- let (transaction, manualEvent) = node.Value
- this.Lock(transaction)
- lock (manualEvent) (fun() -> if not manualEvent.SafeWaitHandle.IsClosed
- then manualEvent.Set() |> ignore))
+ let sync = obj()
+ member this.Owner
+ with get () = lock sync (fun () -> owner)
+ and set v = lock sync (fun () -> owner <- v)
+ member this.Locked with get () = this.Owner <> null
+ member this.Lock(transaction) =
+ let evt = lock sync (fun() ->
+ if this.Owner = null then
+ if transaction <> null then
+ this.Owner <- transaction
+ None
+ else
+ if transaction <> this.Owner then
+ let manualEvent = new ManualResetEvent(false)
+ let pair = (transaction,manualEvent)
+ pending.AddLast pair |> ignore
+ if transaction <> null then
+ transaction.TransactionCompleted.Add (fun e ->
+ lock sync (fun() -> pending.Remove(pair)) |> ignore
+ lock manualEvent (fun() -> if not manualEvent.SafeWaitHandle.IsClosed then
+ manualEvent.Set() |> ignore))
+ (Some manualEvent)
+ else None)
+ match evt with
+ | None -> ()
+ | (Some manualEvent) ->
+ manualEvent.WaitOne() |> ignore
+ lock(manualEvent) manualEvent.Close
+
+ member this.Unlock () =
+ lock(sync) (fun () ->
+ this.Owner <- null
+ let mutable node : LinkedListNode<Transaction*ManualResetEvent> = null
+ if pending.Count > 0 then
+ node <- pending.First
+ pending.RemoveFirst()
+ if node <> null then
+ let (transaction, manualEvent) = node.Value
+ this.Lock(transaction)
+ lock (manualEvent) (fun() -> if not manualEvent.SafeWaitHandle.IsClosed
+ then manualEvent.Set() |> ignore))
View
27 Xoltar.Core/TransactionalDictionary.fs
@@ -34,7 +34,7 @@ type internal TransactionValues<'TKey,'TValue
let transactionValues =
if backingStore.IsReadOnly then
raise (System.ArgumentException("Source dictionary is ReadOnly"))
- new Dictionary<'TKey, 'TValue option>()
+ Dictionary<'TKey, 'TValue option>()
//The undo data needed to undo changes if a rollback happens during
//a 2-phase commit. Generated during the IEnlistmentNotification.Prepare method.
@@ -67,7 +67,7 @@ type internal TransactionValues<'TKey,'TValue
prepared <- true
let current () =
- let dict = new Dictionary<'TKey, 'TValue>(backingStore)
+ let dict = Dictionary<'TKey, 'TValue>(backingStore)
update dict |> ignore
seq { for kv in dict do yield kv }
@@ -129,10 +129,10 @@ type internal TransactionValues<'TKey,'TValue
member this.Keys = current()
|> Seq.map (fun kv -> kv.Key)
- |> fun s -> new List<'TKey>(s) :> ICollection<'TKey>
+ |> fun s -> List<'TKey>(s) :> ICollection<'TKey>
member this.Values = current()
|> Seq.map (fun kv -> kv.Value)
- |> fun s -> new List<'TValue>(s) :> ICollection<'TValue>
+ |> fun s -> List<'TValue>(s) :> ICollection<'TValue>
interface System.Transactions.IEnlistmentNotification
with
@@ -147,7 +147,10 @@ type internal TransactionValues<'TKey,'TValue
try
prep()
enlistment.Prepared()
- with e -> enlistment.ForceRollback(e)
+ with e ->
+ //Prepare should never throw exceptions - if an exception happens, it
+ //can be passed to enlistment.ForceRollback.
+ enlistment.ForceRollback(e)
member this.Rollback(enlistment) =
for kv in undo do
updateWithPair backingStore kv
@@ -172,7 +175,7 @@ type TransactionalDictionary<'TKey, 'TValue
and 'TValue: equality>
(backingStore:IDictionary<'TKey,'TValue>) =
- let transactions = new Dictionary<Transaction,TransactionValues<'TKey, 'TValue>>()
+ let transactions = Dictionary<Transaction,TransactionValues<'TKey, 'TValue>>()
let sync = obj()
let transactionLock = new TransactionLock()
let getValues txn : IDictionary<'TKey, 'TValue> =
@@ -203,23 +206,23 @@ type TransactionalDictionary<'TKey, 'TValue
let tv = getTxnValues() :> IEnumerable<KeyValuePair<'TKey,'TValue>>
tv.GetEnumerator()
member this.Clear () =
- let tv = getTxnValues() :> ICollection<KeyValuePair<'TKey,'TValue>>
+ let tv = getTxnValues()
tv.Clear()
member this.Add(kv) =
- let tv = getTxnValues() :> ICollection<KeyValuePair<'TKey,'TValue>>
+ let tv = getTxnValues()
tv.Add(kv)
member this.Contains(kv) =
- let tv = getTxnValues() :> ICollection<KeyValuePair<'TKey,'TValue>>
+ let tv = getTxnValues()
tv.Contains(kv)
member this.Remove(kv:KeyValuePair<'TKey,'TValue>) =
- let tv = getTxnValues() :> ICollection<KeyValuePair<'TKey,'TValue>>
+ let tv = getTxnValues()
tv.Remove(kv)
member this.CopyTo(array, arrayIndex) =
- let tv = getTxnValues() :> ICollection<KeyValuePair<'TKey,'TValue>>
+ let tv = getTxnValues()
tv.CopyTo(array, arrayIndex)
member this.Count
with get () =
- let tv = getTxnValues() :> ICollection<KeyValuePair<'TKey,'TValue>>
+ let tv = getTxnValues()
tv.Count
member this.IsReadOnly with get ()= false
member this.Add(key, value) =

0 comments on commit c71f564

Please sign in to comment.