-
Notifications
You must be signed in to change notification settings - Fork 16
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
Add MutexMap MutexSection/RMutexSection #47
base: master
Are you sure you want to change the base?
Conversation
This change will also help refactoring PretendoNetwork/nex-protocols-common-go#28 |
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.
I'm failing to see why we need the MapInterface
, can't we just give the real map as an argument on the Atomic
callbacks?
Some of the naming here would also likely be confusing/misleading. Also the use of the name mm := NewMutexMap[int, string]()
mm.Atomic(func(mapInterface *MapInterface[int, string]) {
for i := 0; i < 10; i++ {
fmt.Println(mapInterface.Size())
if i == 5 {
return
}
mapInterface.Set(i, "test")
}
}) This prints size changes for every iteration. If this were truly atomic I would assume that no changes to |
It's atomic in concurrent terms. All the operations inside the callback will be done without other threads interfering. I'm open to name suggestions such as |
To keep all the utility functions the same. That way if we find other places where this is needed we don't need to rewrite the logic too much. |
That's fair. I was thinking in terms of atomic operations typically seen in systems such as databases (but can be used outside of them) which take the form of "all-or-nothing" transactions. All operations either happen, or none do, with the results all applying at the same time if they do apply These kinds of atomic operations here would be linearizability, so maybe taking some language from here would clear up the specific type of atomic operations being done here? Or at the very least updating the Godoc comment to note which kind of atomicity is being used |
29c5acd
to
4cb78b1
Compare
4cb78b1
to
9da218d
Compare
Please re-review. The changes will be useful in the future even if the original bug this aimed to fix was fixed in a different way. |
9da218d
to
008e0d2
Compare
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.
Just a little typo
// RawMap implements a map type with helper functions to operate it. | ||
type RawMap[K comparable, V any] struct { | ||
real map[K]V | ||
} |
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.
This can just be made into a type alias rather than creating a whole struct
// RawMap implements a map type with helper functions to operate it. | |
type RawMap[K comparable, V any] struct { | |
real map[K]V | |
} | |
// RawMap implements a map type with helper functions to operate it. | |
type RawMap[K comparable, V any] map[K]V |
Then it can just be used like a regular map, how real
is being used internally. Though I'm not sure what the benefit of this type is right now, since all it seems to do is wrap a map and then give it helper functions for things Go already supports?
Like why use RawMap.Delete()
rather than just using a normal map
and the built in delete()
?
// MutexMap implements a map type with go routine safe accessors through mutex locks. Embeds sync.RWMutex | ||
type MutexMap[K comparable, V any] struct { | ||
*sync.RWMutex | ||
real map[K]V | ||
mutex *sync.RWMutex | ||
rawMap RawMap[K, V] | ||
} |
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.
We prefer if structs are defined directly before their methods, so this should be moved further down
The previous implementation of the
MutexMap
didn't allow performing multiple operations (Get
+Delete
orGet
+Set
) in a mutually exclusive way, as locking the map manually withLock()
would cause a recursive lock when trying to call any of the methods. For that reason, I split theMutexMap
intoMutexMap
andMap
. Both structs have the same methods, but only theMutexMap
methods actually lock the map. I also addedMutexSection
andRMutexSection
methods toMutexMap
, with runs a callback with aMap
, that allows performing multiple operations to the map in an atomic way.