/*
 * 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 "fw_dunit.hpp"

#include <mutex>

#include "util/concurrent/binary_semaphore.hpp"
#include "util/concurrent/spinlock_mutex.hpp"

namespace {  // NOLINT(google-build-namespaces)

using apache::geode::client::binary_semaphore;
using apache::geode::util::concurrent::spinlock_mutex;

DUNIT_TASK(s1p1, Basic)
  {
    spinlock_mutex s;
    { std::lock_guard<spinlock_mutex> lk(s); }
  }
END_TASK(Basic)

spinlock_mutex lock;
std::chrono::steady_clock::time_point btime;

class ThreadA {
 public:
  ThreadA(binary_semaphore& triggerA, binary_semaphore& triggerM)
      : triggerA_{triggerA}, triggerM_{triggerM} {}

  ~ThreadA() { stop(); }

  void start() {
    thread_ = std::thread{[this]() { run(); }};
  }

  void stop() {
    if (thread_.joinable()) {
      thread_.join();
    }
  }

 protected:
  void run() {
    std::lock_guard<spinlock_mutex> lk(lock);
    LOG("ThreadA: Acquired lock x.");
    triggerM_.release();
    triggerA_.acquire();

    LOG("ThreadA: Released lock.");
  }

 protected:
  std::thread thread_;
  binary_semaphore& triggerA_;
  binary_semaphore& triggerM_;
};

class ThreadB {
 public:
  ThreadB(binary_semaphore& triggerB, binary_semaphore& triggerM)
      : triggerB_{triggerB}, triggerM_{triggerM} {}

  ~ThreadB() { stop(); }

  void start() {
    thread_ = std::thread{[this]() { run(); }};
  }

  void stop() {
    if (thread_.joinable()) {
      thread_.join();
    }
  }

 protected:
  void run() {
    triggerB_.acquire();

    std::lock_guard<spinlock_mutex> lk(lock);
    btime = std::chrono::steady_clock::now();
    LOG("ThreadB: Acquired lock.");
    triggerM_.release();
  }

 protected:
  std::thread thread_;
  binary_semaphore& triggerB_;
  binary_semaphore& triggerM_;
};

DUNIT_TASK(s1p1, TwoThreads)
  {
    binary_semaphore triggerA{0};
    binary_semaphore triggerB{0};
    binary_semaphore triggerM{0};

    ThreadA threadA{triggerA, triggerM};
    ThreadB threadB{triggerB, triggerM};

    threadA.start();
    threadB.start();

    // A runs, locks the spinlock, and triggers me. B is idle.
    triggerM.acquire();
    // A is now idle, but holds lock. Tell B to acquire the lock
    auto stime = std::chrono::steady_clock::now();
    triggerB.release();
    SLEEP(5000);
    // B will be stuck until we tell A to release it.
    triggerA.release();
    // wait until B tells us it has acquired the lock.
    triggerM.acquire();

    // Now diff btime (when B acquired the lock) and stime to see that it
    // took longer than the 5000 seconds before A released it.
    auto delta =
        std::chrono::duration_cast<std::chrono::milliseconds>(btime - stime)
            .count();

    LOG("acquire delay was " + std::to_string(delta));
    ASSERT(delta >= 4900, "Expected 5 second or more spinlock delay");
    // Note the test is against 4900 instead of 5000 as there are some
    // measurement
    // issues. Often delta comes back as 4999 on linux.

    threadA.stop();
    threadB.stop();
  }
END_TASK(TwoThreads)

}  // namespace
