// 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.

#include "kudu/util/rw_mutex.h"

#include <cerrno>
#include <cstring>
#include <mutex>
#include <ostream>

#include <glog/logging.h>

#include "kudu/gutil/map-util.h"
#include "kudu/util/env.h"

using std::lock_guard;

namespace {

void unlock_rwlock(pthread_rwlock_t* rwlock) {
  int rv = pthread_rwlock_unlock(rwlock);
  DCHECK_EQ(0, rv) << strerror(rv);
}

} // anonymous namespace

namespace kudu {

RWMutex::RWMutex()
#ifndef NDEBUG
    : writer_tid_(0)
#endif
{
  Init(Priority::PREFER_READING);
}

RWMutex::RWMutex(Priority prio)
#ifndef NDEBUG
    : writer_tid_(0)
#endif
{
  Init(prio);
}

void RWMutex::Init(Priority prio) {
#ifdef __linux__
  // Adapt from priority to the pthread type.
  int kind = PTHREAD_RWLOCK_PREFER_READER_NP;
  switch (prio) {
    case Priority::PREFER_READING:
      kind = PTHREAD_RWLOCK_PREFER_READER_NP;
      break;
    case Priority::PREFER_WRITING:
      kind = PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP;
      break;
  }

  // Initialize the new rwlock with the user's preference.
  pthread_rwlockattr_t attr;
  int rv = pthread_rwlockattr_init(&attr);
  DCHECK_EQ(0, rv) << strerror(rv);
  rv = pthread_rwlockattr_setkind_np(&attr, kind);
  DCHECK_EQ(0, rv) << strerror(rv);
  rv = pthread_rwlock_init(&native_handle_, &attr);
  DCHECK_EQ(0, rv) << strerror(rv);
  rv = pthread_rwlockattr_destroy(&attr);
  DCHECK_EQ(0, rv) << strerror(rv);
#else
  int rv = pthread_rwlock_init(&native_handle_, NULL);
  DCHECK_EQ(0, rv) << strerror(rv);
#endif
}

RWMutex::~RWMutex() {
  int rv = pthread_rwlock_destroy(&native_handle_);
  DCHECK_EQ(0, rv) << strerror(rv);
}

void RWMutex::ReadLock() {
  CheckLockState(LockState::NEITHER);
  int rv = pthread_rwlock_rdlock(&native_handle_);
  DCHECK_EQ(0, rv) << strerror(rv);
  MarkForReading();
}

void RWMutex::ReadUnlock() {
  CheckLockState(LockState::READER);
  UnmarkForReading();
  unlock_rwlock(&native_handle_);
}

bool RWMutex::TryReadLock() {
  CheckLockState(LockState::NEITHER);
  int rv = pthread_rwlock_tryrdlock(&native_handle_);
  if (rv == EBUSY) {
    return false;
  }
  DCHECK_EQ(0, rv) << strerror(rv);
  MarkForReading();
  return true;
}

void RWMutex::WriteLock() {
  CheckLockState(LockState::NEITHER);
  int rv = pthread_rwlock_wrlock(&native_handle_);
  DCHECK_EQ(0, rv) << strerror(rv);
  MarkForWriting();
}

void RWMutex::WriteUnlock() {
  CheckLockState(LockState::WRITER);
  UnmarkForWriting();
  unlock_rwlock(&native_handle_);
}

bool RWMutex::TryWriteLock() {
  CheckLockState(LockState::NEITHER);
  int rv = pthread_rwlock_trywrlock(&native_handle_);
  if (rv == EBUSY) {
    return false;
  }
  DCHECK_EQ(0, rv) << strerror(rv);
  MarkForWriting();
  return true;
}

#ifndef NDEBUG

void RWMutex::AssertAcquired() const {
  lock_guard<simple_spinlock> l(tid_lock_);
  CHECK(ContainsKey(reader_tids_, Env::Default()->gettid()) ||
        Env::Default()->gettid() == writer_tid_);
}

void RWMutex::AssertAcquiredForReading() const {
  lock_guard<simple_spinlock> l(tid_lock_);
  CHECK(ContainsKey(reader_tids_, Env::Default()->gettid()));
}

void RWMutex::AssertAcquiredForWriting() const {
  lock_guard<simple_spinlock> l(tid_lock_);
  CHECK_EQ(Env::Default()->gettid(), writer_tid_);
}

void RWMutex::CheckLockState(LockState state) const {
  pid_t my_tid = Env::Default()->gettid();
  bool is_reader;
  bool is_writer;
  {
    lock_guard<simple_spinlock> l(tid_lock_);
    is_reader = ContainsKey(reader_tids_, my_tid);
    is_writer = writer_tid_ == my_tid;
  }

  switch (state) {
    case LockState::NEITHER:
      CHECK(!is_reader) << "Invalid state, already holding lock for reading";
      CHECK(!is_writer) << "Invalid state, already holding lock for writing";
      break;
    case LockState::READER:
      CHECK(!is_writer) << "Invalid state, already holding lock for writing";
      CHECK(is_reader) << "Invalid state, wasn't holding lock for reading";
      break;
    case LockState::WRITER:
      CHECK(!is_reader) << "Invalid state, already holding lock for reading";
      CHECK(is_writer) << "Invalid state, wasn't holding lock for writing";
      break;
  }
}

void RWMutex::MarkForReading() {
  lock_guard<simple_spinlock> l(tid_lock_);
  reader_tids_.insert(Env::Default()->gettid());
}

void RWMutex::MarkForWriting() {
  lock_guard<simple_spinlock> l(tid_lock_);
  writer_tid_ = Env::Default()->gettid();
}

void RWMutex::UnmarkForReading() {
  lock_guard<simple_spinlock> l(tid_lock_);
  reader_tids_.erase(Env::Default()->gettid());
}

void RWMutex::UnmarkForWriting() {
  lock_guard<simple_spinlock> l(tid_lock_);
  writer_tid_ = 0;
}

#endif

} // namespace kudu
