/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 catalog

import (
	"sync"
)

type Heartbeats struct {
	instances map[Instance]struct{}
	sync.Mutex
}

func NewHeartbeats() *Heartbeats {
	return &Heartbeats{
		instances: map[Instance]struct{}{},
	}
}

func (h *Heartbeats) ResetAndCollect() []Instance {
	h.Lock()
	currentInstances := h.instances
	h.instances = map[Instance]struct{}{}
	h.Unlock()
	var instances []Instance
	for k := range currentInstances {
		instances = append(instances, k)
	}
	return instances
}

func (h *Heartbeats) Add(instance Instance) {
	h.Lock()
	h.instances[instance] = struct{}{}
	h.Unlock()
}

func (h *Heartbeats) Remove(instance Instance) {
	h.Lock()
	delete(h.instances, instance)
	h.Unlock()
}
