First Commit of Voltha-Go-Controller from Radisys

Change-Id: I8e2e908e7ab09a4fe3d86849da18b6d69dcf4ab0
diff --git a/internal/pkg/util/concurrentmap.go b/internal/pkg/util/concurrentmap.go
new file mode 100644
index 0000000..f16bb29
--- /dev/null
+++ b/internal/pkg/util/concurrentmap.go
@@ -0,0 +1,87 @@
+/*
+* Copyright 2022-present Open Networking Foundation
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package util
+
+import (
+	"sync"
+
+	"go.uber.org/atomic"
+)
+
+// ConcurrentMap implements a wrapper on top of SyncMap so that the count is also maintained
+type ConcurrentMap struct {
+	syncMap sync.Map
+	count   *atomic.Uint64
+	MapLock sync.RWMutex
+}
+
+// NewConcurrentMap - Initializes new ConcurentMap Object
+func NewConcurrentMap() *ConcurrentMap {
+	var cm ConcurrentMap
+	cm.count = atomic.NewUint64(0)
+	return &cm
+}
+
+// Get - Gets return the value store in the sync map
+//If value is present, the result will be true else false
+func (cm *ConcurrentMap) Get(key interface{}) (value interface{}, result bool) {
+	return cm.syncMap.Load(key)
+}
+
+// Set - Store the value in sync map against the key provided
+func (cm *ConcurrentMap) Set(key, value interface{}) {
+	if cm.count == nil {
+		cm.count = atomic.NewUint64(0)
+	}
+	_, exists := cm.syncMap.Load(key)
+	cm.syncMap.Store(key, value)
+	if !exists {
+		cm.count.Inc()
+	}
+}
+
+// Remove - Removes the key-value pair from the sync map
+func (cm *ConcurrentMap) Remove(key interface{}) bool {
+
+	if _, ok := cm.syncMap.Load(key); ok {
+		cm.syncMap.Delete(key)
+		cm.count.Dec()
+		return true
+	}
+	return false
+}
+
+// Range calls f sequentially for each key and value present in the sync map.
+// If f returns false, range stops the iteration.
+//
+// Range does not necessarily correspond to any consistent snapshot of the Sync Map's
+// contents: no key will be visited more than once, but if the value for any key
+// is stored or deleted concurrently, Range may reflect any mapping for that key
+// from any point during the Range call.
+//
+// Range may be O(N) with the number of elements in the sync map even if f returns
+// false after a constant number of calls.
+func (cm *ConcurrentMap) Range(f func(key, value interface{}) bool) {
+	cm.syncMap.Range(f)
+}
+
+// Length - return the no of entries present in the map
+func (cm *ConcurrentMap) Length() uint64 {
+	if cm.count == nil {
+		return 0
+	}
+	return cm.count.Load()
+}