Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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

…s, Phil!
  • Loading branch information...
commit c71f564079c81dc83d570dff58d298ba5c58c8d3 1 parent 7cab6e3
Bryn Keller authored
Showing with 56 additions and 51 deletions.
  1. +41 −39 Xoltar.Core/TransactionLock.fs
  2. +15 −12 Xoltar.Core/TransactionalDictionary.fs
80 Xoltar.Core/TransactionLock.fs
View
@@ -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))
27 Xoltar.Core/TransactionalDictionary.fs
View
@@ -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) =
Please sign in to comment.
Something went wrong with that request. Please try again.