github.com/zhyoulun/cilium@v1.6.12/pkg/lock/semaphored_mutex.go (about)

     1  // Copyright 2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package lock
    16  
    17  import (
    18  	"context"
    19  
    20  	"golang.org/x/sync/semaphore"
    21  )
    22  
    23  // SemaphoredMutex is a semaphored mutex that provides a RWLocker interface.
    24  type SemaphoredMutex struct {
    25  	semaphore *semaphore.Weighted
    26  }
    27  
    28  // using the same value set in `go/src/rwmutex.go#rwmutexMaxReaders
    29  const maxReaders = 1 << 30
    30  
    31  // NewSemaphoredMutex returns a new SemaphoredMutex.
    32  func NewSemaphoredMutex() SemaphoredMutex {
    33  	return SemaphoredMutex{
    34  		semaphore: semaphore.NewWeighted(maxReaders),
    35  	}
    36  }
    37  
    38  func (i *SemaphoredMutex) Lock() {
    39  	// It's fine ignoring error since the error is only caused by passing a
    40  	// context with a deadline.
    41  	i.semaphore.Acquire(context.Background(), maxReaders)
    42  }
    43  
    44  // UnlockToRLock releases the current lock for writing but it still keeps it
    45  // for reading purposes.
    46  func (i *SemaphoredMutex) UnlockToRLock() {
    47  	i.semaphore.Release(maxReaders - 1)
    48  }
    49  
    50  func (i *SemaphoredMutex) Unlock() {
    51  	i.semaphore.Release(maxReaders)
    52  }
    53  
    54  func (i *SemaphoredMutex) RLock() {
    55  	// It's fine ignoring error since the error is only caused by passing a
    56  	// context with a deadline.
    57  	i.semaphore.Acquire(context.Background(), 1)
    58  }
    59  
    60  func (i *SemaphoredMutex) RUnlock() {
    61  	i.semaphore.Release(1)
    62  }