shad-go/keylock
2023-03-27 23:30:25 +04:00
..
keylock.go go fix old build tags. 2022-03-15 23:49:56 +03:00
keylock_test.go Always call unlock after successful lock 2023-03-27 23:30:25 +04:00
README.md Expand keylock task description 2023-03-27 19:27:25 +04:00
speed_test.go Fix 2022-03-18 23:25:42 +03:00

keylock

Напишите примитив синхронизации, позволяющий "лочить" строки из множества.

В обычном sync.Mutex лок всего один. В один момент времени этот лок может находиться у одной горутины. В нашем примитиве локов может быть сколько угодно. Каждый лок мы идентифицируем ключём - строкой. Каждая горутина приходит к нам со списком ключей и хочет захватить сразу все локи из этого списка.

В итоге, внутри критической секции может быть сколько угодно горутин, но у всех них множества ключей попарно не пересекаются.

Например, если к нам придёт 3 горутины:

  1. LockKeys({a, b})
  2. LockKeys({b})
  3. LockKeys({c})

То в критической секции одновременно могут находиться:

  • 1 и 3
  • 2 и 3

А вот 1 и 2 одновременно в критическую секцию зайти не могут, потому что у них множества ключей пересекаются.

Метод LockKeys должен блокироваться, пока не удастся захватить все ключи, либо пока операция не будет отменена через канал cancel.

package keylock

type KeyLock interface {
    // LockKeys locks all keys from provided set.
    // 
    // Upon successful completion, function guarantees that no other call with intersecting set of keys
    // will finish, until unlock() is called.
    //
    // If cancel channel is closed, function stops trying to lock received keys and returns immediately
    LockKeys(keys []string, cancel <-chan struct{}) (canceled bool, unlock func())
}

Реализация не должна содержать busy wait. То есть, если вызов LockKeys не может выполниться, потому что какие-то из ключей залочены другими горутинами, то текущая горутина должна засыпать.