Add withLock keyword for locking/unlocking mutexes around code#4350
Add withLock keyword for locking/unlocking mutexes around code#4350d-torrance wants to merge 2 commits into
Conversation
|
I don't like this syntax. I also don't think Jay's suggestion involved the user specifying the mutex. My impression after we talked was that there are two important cases:
Based on my own experience trying to scale parallel computations, here is my current best proposal for the latter: make The main downside I can think of is that you're forced to store the output in the cache, which can get annoying on very large thread counts (e.g. trying to compute and cache One alternative is introducing a similar syntax that just locks but doesn't store, so maybe something like this: ht#k = (...) -- always compute and store
ht#k ??= (...) -- compute if not cached and store
ht#k ?:= (...) -- compute if not locked, but the := implies local, so nothing is storedHere is a real-life example, since basis(ZZ, Module) := Matrix => (d,M) -> M.cache#(basis, d) ?:= (...)Once computation starts, a mutex is placed in I see a potential critique that not using a word like "lock" anywhere here might make the syntax hard to guess, but I think we could resolve this with a convention of where mutexes should be stored, e.g: basis(ZZ, Module) := Matrix => (d,M) -> M.mutex#(basis, d) ?:= (...)where |
|
The goal here is to have something very general that can wrap arbitrary code like all the modifications of global variables in #4299. The syntax I think is essentially what Jay suggested, except |
withLock(mutex, (
...
))Also, I've already been using your |
|
One issue with Maybe we could make it more flexible?
|
|
Also, regarding the parentheses -- I think the only way |
|
My point was that we can't (and perhaps shouldn't) force the syntax of another language into Macaulay2 if the grammar isn't the same. It's like writing Farsi with English characters; Farsi idioms are beautiful but don't look good in Finglish XD Regarding global mutexes, I think the best solution is to put it in the FunctionClosure, which is not global and can easily be garbage collected if necessary. |
👍
Which FunctionClosure? All we have at this point is a |
|
I think the suggestion that @mahrud has about putting mutexes in the function closure is somewhat orthogonal to the problem I think this tool solves. @mahrud The version I'm proposing does not automatically produce a mutex. I view this as a simpler wrapper to around mutexes to make them safe against exceptions and early returns, both of which are a significant cause of mutexes never getting unlocked. The intent is to produce something that when a user does really need to use a mutex, the work is easier. I agree overall that I would prefer that most users never touch a mutex and use higher level constructs to ensure thread safety. The semantics that @d-torrance is proposing here are essentially what I want. Again, I still view this as a lower level tool, just a safer one. The specific syntax is not of the highest importance to me but I don't particularly like the current style if only because it's not clear that the code is executed with the lock held (because it's different from most other functions). A notation like PS: withStaticMutex = (f) -> (
mutex := new Mutex;
f (mutex)
)
someMethod(ZZ,ZZ) := withStaticMutex ((mutex) ->
(a, b) -> ( body of the function potentially referencing mutex ))This exploits the ability of function closures to capture frames. the name withStaticMutex is a reference to static local variables in c++ and is a bit of a terrible name. Also, this doesn't do any of the automatic locking one might want, it's just a way to associate the data to a function using current code. |
|
Using keywords with i1 : elapsedTime_foo bar
stdio:1:11:(3):[1]: error: syntax error at '_'If we're going to add a new code type, maybe a more general Python-like context manager syntax would be nice? We could define |
|
Closing in favor of #4367 |
As suggested by @jkyang92 in #4299 (comment). This way, we have a way to not worry about getting stuck with a locked mutex if something happens before we have a chance to unlock it.
AI Disclosure
Claude Code wrote the first draft of the documentation for
withLock(but I ended up rewriting most of it...)