// 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 <cstdint>
#include <mutex>
#include <ostream>
#include <thread>
#include <vector>

#include <glog/logging.h>
#include <gtest/gtest.h>

#include "kudu/util/atomic.h"
#include "kudu/util/locks.h"
#include "kudu/util/monotime.h"
#include "kudu/util/rw_mutex.h"
#include "kudu/util/test_util.h"

using std::lock_guard;
using std::thread;
using std::try_to_lock;
using std::unique_lock;
using std::vector;

namespace kudu {

class RWMutexTest : public KuduTest,
                    public ::testing::WithParamInterface<RWMutex::Priority> {
 public:
  RWMutexTest()
     : lock_(GetParam()) {
  }
 protected:
  RWMutex lock_;
};

// Instantiate every test for each kind of RWMutex priority.
INSTANTIATE_TEST_SUITE_P(Priorities, RWMutexTest,
                         ::testing::Values(RWMutex::Priority::PREFER_READING,
                                           RWMutex::Priority::PREFER_WRITING));

// Multi-threaded test that tries to find deadlocks in the RWMutex wrapper.
TEST_P(RWMutexTest, TestDeadlocks) {
  uint64_t number_of_writes = 0;
  AtomicInt<uint64_t> number_of_reads(0);

  AtomicBool done(false);
  vector<thread> threads;

  // Start several blocking and non-blocking read-write workloads.
  for (int i = 0; i < 2; i++) {
    threads.emplace_back([&](){
      while (!done.Load()) {
        lock_guard<RWMutex> l(lock_);
        number_of_writes++;
      }
    });
    threads.emplace_back([&](){
      while (!done.Load()) {
        unique_lock<RWMutex> l(lock_, try_to_lock);
        if (l.owns_lock()) {
          number_of_writes++;
        }
      }
    });
  }

  // Start several blocking and non-blocking read-only workloads.
  for (int i = 0; i < 2; i++) {
    threads.emplace_back([&](){
      while (!done.Load()) {
        shared_lock<RWMutex> l(lock_);
        number_of_reads.Increment();
      }
    });
    threads.emplace_back([&](){
      while (!done.Load()) {
        shared_lock<RWMutex> l(lock_, try_to_lock);
        if (l.owns_lock()) {
          number_of_reads.Increment();
        }
      }
    });
  }

  SleepFor(MonoDelta::FromSeconds(1));
  done.Store(true);
  for (auto& t : threads) {
    t.join();
  }

  shared_lock<RWMutex> l(lock_);
  LOG(INFO) << "Number of writes: " << number_of_writes;
  LOG(INFO) << "Number of reads: " << number_of_reads.Load();
}

#ifndef NDEBUG
// Tests that the RWMutex wrapper catches basic usage errors. This checking is
// only enabled in debug builds.
TEST_P(RWMutexTest, TestLockChecking) {
  EXPECT_DEATH(({
    lock_.ReadLock();
    lock_.ReadLock();
  }), "already holding lock for reading");

  EXPECT_DEATH(({
    CHECK(lock_.TryReadLock());
    CHECK(lock_.TryReadLock());
  }), "already holding lock for reading");

  EXPECT_DEATH(({
    lock_.ReadLock();
    lock_.WriteLock();
  }), "already holding lock for reading");

  EXPECT_DEATH(({
    CHECK(lock_.TryReadLock());
    CHECK(lock_.TryWriteLock());
  }), "already holding lock for reading");

  EXPECT_DEATH(({
    lock_.WriteLock();
    lock_.ReadLock();
  }), "already holding lock for writing");

  EXPECT_DEATH(({
    CHECK(lock_.TryWriteLock());
    CHECK(lock_.TryReadLock());
  }), "already holding lock for writing");

  EXPECT_DEATH(({
    lock_.WriteLock();
    lock_.WriteLock();
  }), "already holding lock for writing");

  EXPECT_DEATH(({
    CHECK(lock_.TryWriteLock());
    CHECK(lock_.TryWriteLock());
  }), "already holding lock for writing");

  EXPECT_DEATH(({
    lock_.ReadUnlock();
  }), "wasn't holding lock for reading");

  EXPECT_DEATH(({
    lock_.WriteUnlock();
  }), "wasn't holding lock for writing");

  EXPECT_DEATH(({
    lock_.ReadLock();
    lock_.WriteUnlock();
  }), "already holding lock for reading");

  EXPECT_DEATH(({
    CHECK(lock_.TryReadLock());
    lock_.WriteUnlock();
  }), "already holding lock for reading");

  EXPECT_DEATH(({
    lock_.WriteLock();
    lock_.ReadUnlock();
  }), "already holding lock for writing");

  EXPECT_DEATH(({
    CHECK(lock_.TryWriteLock());
    lock_.ReadUnlock();
  }), "already holding lock for writing");
}
#endif

} // namespace kudu
