-
Notifications
You must be signed in to change notification settings - Fork 197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix concurrency errors with ConcurrentDictionary #394
Conversation
Hi, |
@kblohm Thanks for the tip. Code is simplified a lot. |
@zyzhu let createTypedVector : _ -> seq<OptionalValue<obj>> -> _ =
let cache = ConcurrentDictionary<_, _ -> _>()
fun typ ->
let valueFactory t =
let par = Expression.Parameter(typeof<seq<OptionalValue<obj>>>)
let body = Expression.Call(createTypedVectorMi.MakeGenericMethod([| t |]), par)
Expression.Lambda<Func<seq<OptionalValue<obj>>, IVector>>(body, par).Compile().Invoke
cache.GetOrAdd(typ, Func<_,_>(valueFactory)) Also, while having a quick look at the module, there is a |
@kblohm Thanks for pointing it out. I added back trygetvalue so that cache shall work. I also changed getCachedCompileProjection |
@zyzhu now you are not really solving the concurrency problem. Right now checking for the value and adding the value is not atomic, that is what |
@kblohm Clearly I'm a newbie on concurrent dictionary. I learned about valuefactory today and fixed it along your lines. |
src/Deedle/FrameUtils.fs
Outdated
cache.Add(typ, f.Invoke) | ||
f.Invoke ) | ||
let cache = ConcurrentDictionary<_, seq<OptionalValue<obj>> -> _>() | ||
let valueFactory typ = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this to:
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)
So the Func<_,_>
call to create the delegate is only executed once
src/Deedle/FrameUtils.fs
Outdated
[| for name, fldTy, proj in getMemberProjections typ -> | ||
name, fldTy, proj.Compile() |] | ||
fun typ -> | ||
cache.GetOrAdd(typ, valueFactory) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar change requested here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two changes requested, otherwise great
@dsyme Thanks for review. I've made above changes. |
Attempt to fix issue 340 in pull 341. I simply replaced dictionary with concurrent dictionary. Ping @tpetricek for review.
#341