Skip to content

Commit

Permalink
Merge pull request #394 from zyzhu/fix_issue_341
Browse files Browse the repository at this point in the history
Fix concurrency errors with ConcurrentDictionary
  • Loading branch information
zyzhu authored Jul 27, 2018
2 parents 23a8db7 + 462ab8f commit 233fa34
Showing 1 changed file with 16 additions and 19 deletions.
35 changes: 16 additions & 19 deletions src/Deedle/FrameUtils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module internal Reflection =
open Microsoft.FSharp.Quotations
open System.Collections
open System.Collections.Generic
open System.Collections.Concurrent

let indexBuilder = IndexBuilder.Instance
let vectorBuilder = VectorBuilder.Instance
Expand Down Expand Up @@ -67,16 +68,14 @@ module internal Reflection =

/// Helper function used when building frames from data tables
let createTypedVector : _ -> seq<OptionalValue<obj>> -> _ =
let cache = Dictionary<_, _>()
(fun typ ->
match cache.TryGetValue(typ) with
| true, res -> res
| false, _ ->
let par = Expression.Parameter(typeof<seq<OptionalValue<obj>>>)
let body = Expression.Call(createTypedVectorMi.MakeGenericMethod([| typ |]), par)
let f = Expression.Lambda<Func<seq<OptionalValue<obj>>, IVector>>(body, par).Compile()
cache.Add(typ, f.Invoke)
f.Invoke )
let cache = ConcurrentDictionary<_, seq<OptionalValue<obj>> -> _>()
let valueFactory =
Func<_,_> (fun typ ->
let par = Expression.Parameter(typeof<seq<OptionalValue<obj>>>)
let body = Expression.Call(createTypedVectorMi.MakeGenericMethod([| typ |]), par)
Expression.Lambda<Func<seq<OptionalValue<obj>>, _>>(body, par).Compile().Invoke)
fun typ ->
cache.GetOrAdd(typ, valueFactory)

let getExpandableProperties (ty:Type) =
ty.GetProperties(BindingFlags.Instance ||| BindingFlags.Public)
Expand Down Expand Up @@ -128,15 +127,13 @@ module internal Reflection =
/// Compile all projections from the type, so that we can run them fast
/// and cache the results with Type as the key, so that we don't have to recompile
let getCachedCompileProjection =
let cache = Dictionary<_, _>()
(fun typ ->
match cache.TryGetValue(typ) with
| true, res -> res
| _ ->
let res = [| for name, fldTy, proj in getMemberProjections typ ->
name, fldTy, proj.Compile() |]
cache.Add(typ, res)
res )
let cache = ConcurrentDictionary<_, (string*Type*Delegate)[]>()
let valueFactory =
Func<_,_> (fun typ ->
[| for name, fldTy, proj in getMemberProjections typ ->
name, fldTy, proj.Compile() |] )
fun typ ->
cache.GetOrAdd(typ, valueFactory)

/// Given a single vector, expand its values into multiple vectors. This may be:
/// - `IDictionary` is expanded based on keys/values
Expand Down

0 comments on commit 233fa34

Please sign in to comment.