// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_PLATFORM_SYNCHRONIZATION_H_
#define RUNTIME_PLATFORM_SYNCHRONIZATION_H_

#include "platform/allocation.h"
#include "platform/threads.h"

#if defined(DART_USE_ABSL)
#include "third_party/absl/synchronization/mutex.h"
#endif

namespace dart {

#if defined(DART_USE_ABSL)
using MutexImpl = absl::Mutex;
using ConditionVariableImpl = absl::CondVar;
#elif defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) ||          \
    defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID)
using MutexImpl = pthread_mutex_t;
using ConditionVariableImpl = pthread_cond_t;
#elif defined(DART_HOST_OS_WINDOWS)
using MutexImpl = SRWLOCK;
using ConditionVariableImpl = CONDITION_VARIABLE;
#else
#error Unknown target os.
#endif

// Mark when we are running in a signal handler (Linux, Android) or with a
// suspended thread (Windows, Mac, Fuchia). During this time, we cannot take
// locks.
class DisallowMutexLockingScope : public ValueObject {
#if defined(DEBUG)
 public:
  DisallowMutexLockingScope() {
    ASSERT(!is_active_);
    is_active_ = true;
  }

  ~DisallowMutexLockingScope() { is_active_ = false; }

  static bool is_active() { return is_active_; }

 private:
  static inline thread_local bool is_active_ = false;
#endif  // DEBUG
};

class Mutex {
 public:
  Mutex();
  ~Mutex();

  bool IsOwnedByCurrentThread() const {
    return owner_.IsOwnedByCurrentThread();
  }

  void Lock();
  bool TryLock();  // Returns false if lock is busy and locking failed.
  void Unlock();

 private:
  MutexImpl mutex_;
  platform::ThreadBoundResource owner_;

  friend class ConditionVariable;
  DISALLOW_COPY_AND_ASSIGN(Mutex);
};

class ConditionVariable {
 public:
  enum WaitResult { kNotified, kTimedOut };
  static constexpr int64_t kNoTimeout = 0;

  ConditionVariable();
  ~ConditionVariable();

  WaitResult Wait(Mutex* mutex, int64_t timeout_millis = kNoTimeout);

  WaitResult WaitMicros(Mutex* mutex, int64_t timeout_micros = kNoTimeout);

  void Notify();
  void NotifyAll();

 private:
  ConditionVariableImpl cv_;

  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
};

class Monitor {
 public:
  using WaitResult = ConditionVariable::WaitResult;
  static constexpr WaitResult kNotified = ConditionVariable::kNotified;
  static constexpr WaitResult kTimedOut = ConditionVariable::kTimedOut;

  static constexpr int64_t kNoTimeout = ConditionVariable::kNoTimeout;

  Monitor() {}
  ~Monitor() {}

  bool IsOwnedByCurrentThread() const {
    return mutex_.IsOwnedByCurrentThread();
  }

  bool TryEnter() { return mutex_.TryLock(); }
  void Enter() { return mutex_.Lock(); }
  void Exit() { return mutex_.Unlock(); }

  // Wait for notification or timeout.
  WaitResult Wait(int64_t timeout_millis) {
    return cv_.Wait(&mutex_, timeout_millis);
  }

  WaitResult WaitMicros(int64_t timeout_micros) {
    return cv_.WaitMicros(&mutex_, timeout_micros);
  }

  // Notify waiting threads.
  void Notify() { cv_.Notify(); }

  void NotifyAll() { cv_.NotifyAll(); }

 private:
  Mutex mutex_;  // OS-specific data.
  ConditionVariable cv_;

  DISALLOW_COPY_AND_ASSIGN(Monitor);
};

class ReentrantMonitor {
 public:
  using WaitResult = ConditionVariable::WaitResult;
  static constexpr WaitResult kNotified = ConditionVariable::kNotified;
  static constexpr WaitResult kTimedOut = ConditionVariable::kTimedOut;

  static constexpr int64_t kNoTimeout = ConditionVariable::kNoTimeout;

  ReentrantMonitor() {}
  ~ReentrantMonitor() {}

  bool IsOwnedByCurrentThread() const {
    return owner_ == platform::GetCurrentThreadId();
  }

  bool TryEnter() {
    bool entered = false;
    if (IsOwnedByCurrentThread()) {
      entered = true;
    } else {
      entered = mutex_.TryLock();
      if (entered) {
        owner_ = platform::GetCurrentThreadId();
      }
    }
    if (entered) {
      ++depth_;
      ASSERT(owner_ == platform::GetCurrentThreadId());
    }
    return entered;
  }

  void Enter() {
    ASSERT(depth_ >= 0);
    if (!IsOwnedByCurrentThread()) {
      mutex_.Lock();
      owner_ = platform::GetCurrentThreadId();
    }
    ASSERT(owner_ == platform::GetCurrentThreadId());
    ++depth_;
  }

  void Exit() {
    ASSERT(depth_ > 0);
    ASSERT(owner_ == platform::GetCurrentThreadId());
    if (--depth_ == 0) {
      owner_ = platform::kInvalidThreadId;
      mutex_.Unlock();
    }
  }

  WaitResult Wait(int64_t timeout_millis) {
    ASSERT(IsOwnedByCurrentThread() && depth_ == 1);
    --depth_;
    owner_ = platform::kInvalidThreadId;
    WaitResult result = cv_.Wait(&mutex_, timeout_millis);
    owner_ = platform::GetCurrentThreadId();
    ++depth_;
    return result;
  }

  WaitResult WaitMicros(int64_t timeout_micros) {
    ASSERT(IsOwnedByCurrentThread() && depth_ == 1);
    --depth_;
    owner_ = platform::kInvalidThreadId;
    WaitResult result = cv_.WaitMicros(&mutex_, timeout_micros);
    owner_ = platform::GetCurrentThreadId();
    ++depth_;
    return result;
  }

  // Notify waiting threads.
  void Notify() { cv_.Notify(); }

  void NotifyAll() { cv_.NotifyAll(); }

 private:
  Mutex mutex_;  // OS-specific data.
  ConditionVariable cv_;

  intptr_t depth_ = 0;
  platform::ThreadId owner_ = platform::kInvalidThreadId;

  DISALLOW_COPY_AND_ASSIGN(ReentrantMonitor);
};

}  // namespace dart

#endif  // RUNTIME_PLATFORM_SYNCHRONIZATION_H_
