Skip to content

Commit

Permalink
Synchronize type cache map access/mutations (#106)
Browse files Browse the repository at this point in the history
The serialization layer caches types during serialization and
deserialization. See
[1](https://github.com/stealthrocket/coroutine/blob/d21c0e06b98e87aca6eb4ebfa7901a9e85597d72/types/types.go#L163-L179),
[2](https://github.com/stealthrocket/coroutine/blob/d21c0e06b98e87aca6eb4ebfa7901a9e85597d72/types/typemap.go#L99)
and
[3](https://github.com/stealthrocket/coroutine/blob/d21c0e06b98e87aca6eb4ebfa7901a9e85597d72/types/typemap.go#L146-L169).

If multiple goroutines are serializing or deserializing durable
coroutine state concurrently, a `concurrent map read and map write`
failure may be observed. This PR fixes the issue by synchronizing
goroutines with a mutex.
  • Loading branch information
chriso authored Nov 15, 2023
2 parents d21c0e0 + feaa1b3 commit a3e7e4a
Showing 1 changed file with 12 additions and 0 deletions.
12 changes: 12 additions & 0 deletions types/typemap.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package types
import (
"fmt"
"reflect"
"sync"
"unsafe"
)

Expand Down Expand Up @@ -146,19 +147,30 @@ func (m *typemap) serdeOf(x reflect.Type) (serde, bool) {
type doublemap[K, V comparable] struct {
fromK map[K]V
fromV map[V]K

mu sync.Mutex
}

func (m *doublemap[K, V]) getK(k K) (V, bool) {
m.mu.Lock()
defer m.mu.Unlock()

v, ok := m.fromK[k]
return v, ok
}

func (m *doublemap[K, V]) getV(v V) (K, bool) {
m.mu.Lock()
defer m.mu.Unlock()

k, ok := m.fromV[v]
return k, ok
}

func (m *doublemap[K, V]) add(k K, v V) V {
m.mu.Lock()
defer m.mu.Unlock()

if m.fromK == nil {
m.fromK = make(map[K]V)
m.fromV = make(map[V]K)
Expand Down

0 comments on commit a3e7e4a

Please sign in to comment.