// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
//
// 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.

#ifndef VK_DEBUG_WEAKMAP_HPP_
#define VK_DEBUG_WEAKMAP_HPP_

#include <map>
#include <memory>

namespace vk
{
namespace dbg
{

// WeakMap is an associative container of keys of type K to values of type
// std::weak_ptr<V>.
// WeakMap's iterators will skip over elements where the value has no more
// remaining std::shared_ptr<V> references.
// WeakMap is not thread-safe and requires the use of an external mutex to be
// used by multiple threads, concurrently.
template <typename K, typename V>
class WeakMap
{
	using Map = std::map<K, std::weak_ptr<V>>;
	using MapIterator = typename Map::const_iterator;

public:
	class iterator
	{
	public:
		inline iterator(const MapIterator& it, const MapIterator& end);
		inline void operator++();
		inline bool operator==(const iterator&) const;
		inline bool operator!=(const iterator&) const;
		inline std::pair<K, std::shared_ptr<V>> operator*() const;

	private:
		void skipNull();

		MapIterator it;
		const MapIterator end;
		std::shared_ptr<V> sptr;
	};

	// begin() returns an iterator to the start of the map.
	inline iterator begin() const;

	// end() returns an iterator to the end of the map.
	inline iterator end() const;

	// approx_size() returns an approximate number of entries in the map. This
	// is guaranteed to be greater than or equal to the actual number of
	// elements in the map.
	inline size_t approx_size() const;

	// get() returns the std::shared_ptr<V> value for the given key, or nullptr
	// if the map does not contain the key, or the last remaining
	// std::shared_ptr<V> reference to the value has been dropped.
	inline std::shared_ptr<V> get(const K& key) const;

	// add() attempts to insert the key-value pair into the map.
	// add() returns true if there was no existing entry with the given key,
	// and the pair was added, otherwise false.
	inline bool add(const K& key, const std::shared_ptr<V>& val);

	// remove() attempts to remove the entry with the given key from the map.
	// remove() returns true if there was no existing entry with the given key,
	// and the entry was removed, otherwise false.
	inline bool remove(const K& key);

private:
	// reap() removes any entries that have values with no external references.
	inline void reap();

	Map map;
	size_t reapAtSize = 32;
};

template <typename K, typename V>
WeakMap<K, V>::iterator::iterator(const MapIterator& it, const MapIterator& end) :
    it(it),
    end(end)
{
	skipNull();
}

template <typename K, typename V>
void WeakMap<K, V>::iterator::operator++()
{
	it++;
	skipNull();
}

template <typename K, typename V>
void WeakMap<K, V>::iterator::skipNull()
{
	for(; it != end; ++it)
	{
		// Hold on to the shared_ptr when pointing at this map element.
		// This ensures that the object is not released.
		sptr = it->second.lock();
		if(sptr)
		{
			return;
		}
	}
}

template <typename K, typename V>
bool WeakMap<K, V>::iterator::operator==(const iterator& rhs) const
{
	return it == rhs.it;
}

template <typename K, typename V>
bool WeakMap<K, V>::iterator::operator!=(const iterator& rhs) const
{
	return it != rhs.it;
}

template <typename K, typename V>
std::pair<K, std::shared_ptr<V>> WeakMap<K, V>::iterator::operator*() const
{
	return { it->first, sptr };
}

template <typename K, typename V>
typename WeakMap<K, V>::iterator WeakMap<K, V>::begin() const
{
	return iterator(map.begin(), map.end());
}

template <typename K, typename V>
typename WeakMap<K, V>::iterator WeakMap<K, V>::end() const
{
	return iterator(map.end(), map.end());
}

template <typename K, typename V>
size_t WeakMap<K, V>::approx_size() const
{
	return map.size();
}

template <typename K, typename V>
std::shared_ptr<V> WeakMap<K, V>::get(const K& key) const
{
	auto it = map.find(key);
	return (it != map.end()) ? it->second.lock() : nullptr;
}

template <typename K, typename V>
bool WeakMap<K, V>::add(const K& key, const std::shared_ptr<V>& val)
{
	if(map.size() > reapAtSize)
	{
		reap();
		reapAtSize = map.size() * 2 + 32;
	}
	return map.emplace(key, val).second;
}

template <typename K, typename V>
bool WeakMap<K, V>::remove(const K& key)
{
	return map.erase(key) > 0;
}

template <typename K, typename V>
void WeakMap<K, V>::reap()
{
	for(auto it = map.begin(); it != map.end();)
	{
		if(it->second.expired())
		{
			map.erase(it++);
		}
		else
		{
			++it;
		}
	}
}

}  // namespace dbg
}  // namespace vk

#endif  // VK_DEBUG_WEAKMAP_HPP_
