//===-- ThreadSafeSTLMap.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_ThreadSafeSTLMap_h_
#define liblldb_ThreadSafeSTLMap_h_

#include <map>
#include <mutex>

#include "lldb/lldb-defines.h"

namespace lldb_private {

template <typename _Key, typename _Tp> class ThreadSafeSTLMap {
public:
  typedef std::map<_Key, _Tp> collection;
  typedef typename collection::iterator iterator;
  typedef typename collection::const_iterator const_iterator;
  // Constructors and Destructors
  ThreadSafeSTLMap() : m_collection(), m_mutex() {}

  ~ThreadSafeSTLMap() {}

  bool IsEmpty() const {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    return m_collection.empty();
  }

  void Clear() {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    return m_collection.clear();
  }

  size_t Erase(const _Key &key) {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    return EraseNoLock(key);
  }

  size_t EraseNoLock(const _Key &key) { return m_collection.erase(key); }

  bool GetValueForKey(const _Key &key, _Tp &value) const {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    return GetValueForKeyNoLock(key, value);
  }

  // Call this if you have already manually locked the mutex using the
  // GetMutex() accessor
  bool GetValueForKeyNoLock(const _Key &key, _Tp &value) const {
    const_iterator pos = m_collection.find(key);
    if (pos != m_collection.end()) {
      value = pos->second;
      return true;
    }
    return false;
  }

  bool GetFirstKeyForValue(const _Tp &value, _Key &key) const {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    return GetFirstKeyForValueNoLock(value, key);
  }

  bool GetFirstKeyForValueNoLock(const _Tp &value, _Key &key) const {
    const_iterator pos, end = m_collection.end();
    for (pos = m_collection.begin(); pos != end; ++pos) {
      if (pos->second == value) {
        key = pos->first;
        return true;
      }
    }
    return false;
  }

  bool LowerBound(const _Key &key, _Key &match_key, _Tp &match_value,
                  bool decrement_if_not_equal) const {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    return LowerBoundNoLock(key, match_key, match_value,
                            decrement_if_not_equal);
  }

  bool LowerBoundNoLock(const _Key &key, _Key &match_key, _Tp &match_value,
                        bool decrement_if_not_equal) const {
    const_iterator pos = m_collection.lower_bound(key);
    if (pos != m_collection.end()) {
      match_key = pos->first;
      if (decrement_if_not_equal && key != match_key &&
          pos != m_collection.begin()) {
        --pos;
        match_key = pos->first;
      }
      match_value = pos->second;
      return true;
    }
    return false;
  }

  iterator lower_bound_unsafe(const _Key &key) {
    return m_collection.lower_bound(key);
  }

  void SetValueForKey(const _Key &key, const _Tp &value) {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
    SetValueForKeyNoLock(key, value);
  }

  // Call this if you have already manually locked the mutex using the
  // GetMutex() accessor
  void SetValueForKeyNoLock(const _Key &key, const _Tp &value) {
    m_collection[key] = value;
  }

  std::recursive_mutex &GetMutex() { return m_mutex; }

private:
  collection m_collection;
  mutable std::recursive_mutex m_mutex;

  // For ThreadSafeSTLMap only
  DISALLOW_COPY_AND_ASSIGN(ThreadSafeSTLMap);
};

} // namespace lldb_private

#endif // liblldb_ThreadSafeSTLMap_h_
