storage icon indicating copy to clipboard operation
storage copied to clipboard

Ideas wanted: Rely on language features to enforce locking correctness

Open mtrmac opened this issue 3 years ago • 2 comments

Looking at #1324, #1332, #1379 , it’s not absolutely required but boy it would be nice if we could have the programming language enforce locking invariants

  • That locks that are supposed to be held are held
  • That reads to struct fields only happen with a read lock held
  • That writes to struct fields only happen with a write lock held.

At the thousands of lines of c/storage code, and about half a dozen locks involved, it’s only natural that some mistakes will happen and we could certainly use some help noticing them.

Sadly, Go is very weak for these purposes. So, this is an open-ended call for ideas.

mtrmac avatar Oct 14 '22 03:10 mtrmac


  • I have nothing at all for protecting access to struct fields. AFAICS we could make the struct completely private and wrap everything in getters/setters … written manually. Not worth it.
  • For enforcing API invariants:
    • Interfaces sort of work:
      type unlockedStore interface {
         startReading() readableStore
         startWriting() writableStore
      }
      
      type readableStore interface {
         // readers
         Close()
      }
      // and writableStore similarly
      
      but if the three interfaces are implemented by the same struct, calls within that struct are no longer protected (e.g. a “reader” method can call a “writer” method no the same object)
    • “lock tokens” work:
      type readToken struct {} // unique type, zero cost to pass around
      type writeToken struct {} // unique type, zero cost to pass around
      type store interface { // or just methods on a struct
         startReading() readToken
         stopReading(readToken)
         startWriting() writeToken
         stopWriting(writeToken)
      
         readSomething(readToken)
         writeSomething(writeToken, valueType)
      }
      
      but require all call sites to carry around an extra token value. That has zero or close-to-zero run-time cost, but the code is larger.

Is there something else that would work? Anything that would be worth doing?

mtrmac avatar Oct 14 '22 03:10 mtrmac

  • I have nothing at all for protecting access to struct fields

@vrothberg came up with

type stateful struct {
    lock sync.Mutex
    requiresLock struct {
        field …
    }
}

which is much better than nothing. A downside is that such a type can’t be created with a trivial struct initializer: either .requiresLock.field must be initialized after the struct is created, or requiresLock must become an out-of-line separately-defined named type — that’s probably still well worth the cost.

mtrmac avatar Jan 03 '23 23:01 mtrmac