blob: 380e3aa0b87880099df487dd73157d79a1424749 [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301/*
2* Copyright 2022-present Open Networking Foundation
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.
vinokuma926cb3e2023-03-29 11:41:06 +053014 */
Naveen Sampath04696f72022-06-13 15:19:14 +053015
16package util
17
18import (
19 "sync"
20
21 "go.uber.org/atomic"
22)
23
24// ConcurrentMap implements a wrapper on top of SyncMap so that the count is also maintained
25type ConcurrentMap struct {
Naveen Sampath04696f72022-06-13 15:19:14 +053026 count *atomic.Uint64
vinokuma926cb3e2023-03-29 11:41:06 +053027 syncMap sync.Map
Naveen Sampath04696f72022-06-13 15:19:14 +053028 MapLock sync.RWMutex
29}
30
31// NewConcurrentMap - Initializes new ConcurentMap Object
32func NewConcurrentMap() *ConcurrentMap {
33 var cm ConcurrentMap
34 cm.count = atomic.NewUint64(0)
35 return &cm
36}
37
38// Get - Gets return the value store in the sync map
vinokuma926cb3e2023-03-29 11:41:06 +053039// If value is present, the result will be true else false
Naveen Sampath04696f72022-06-13 15:19:14 +053040func (cm *ConcurrentMap) Get(key interface{}) (value interface{}, result bool) {
41 return cm.syncMap.Load(key)
42}
43
44// Set - Store the value in sync map against the key provided
45func (cm *ConcurrentMap) Set(key, value interface{}) {
46 if cm.count == nil {
47 cm.count = atomic.NewUint64(0)
48 }
49 _, exists := cm.syncMap.Load(key)
50 cm.syncMap.Store(key, value)
51 if !exists {
52 cm.count.Inc()
53 }
54}
55
56// Remove - Removes the key-value pair from the sync map
57func (cm *ConcurrentMap) Remove(key interface{}) bool {
Naveen Sampath04696f72022-06-13 15:19:14 +053058 if _, ok := cm.syncMap.Load(key); ok {
59 cm.syncMap.Delete(key)
60 cm.count.Dec()
61 return true
62 }
63 return false
64}
65
66// Range calls f sequentially for each key and value present in the sync map.
67// If f returns false, range stops the iteration.
68//
69// Range does not necessarily correspond to any consistent snapshot of the Sync Map's
70// contents: no key will be visited more than once, but if the value for any key
71// is stored or deleted concurrently, Range may reflect any mapping for that key
72// from any point during the Range call.
73//
74// Range may be O(N) with the number of elements in the sync map even if f returns
75// false after a constant number of calls.
76func (cm *ConcurrentMap) Range(f func(key, value interface{}) bool) {
77 cm.syncMap.Range(f)
78}
79
80// Length - return the no of entries present in the map
81func (cm *ConcurrentMap) Length() uint64 {
82 if cm.count == nil {
83 return 0
84 }
85 return cm.count.Load()
86}