// 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.
#pragma once

#include "kudu/gutil/macros.h"

#ifdef __linux__
#include "kudu/gutil/atomicops.h"
#include "kudu/gutil/linux_syscall_support.h"
#else
#include "kudu/util/countdown_latch.h"
#endif

#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define FUTEX_PRIVATE_FLAG 128

namespace kudu {

// This class defines a `Notification` abstraction, which allows threads
// to receive notification of a single occurrence of a single event.
//
// NOTE: this class is modeled after absl::Notification but re-implemented
// to not have dependencies on other absl-specific code. If absl is ever
// imported, this can be removed.
//
// The `Notification` object maintains a private boolean "notified" state that
// transitions to `true` at most once. The `Notification` class provides the
// following primary member functions:
//   * `HasBeenNotified() `to query its state
//   * `WaitForNotification*()` to have threads wait until the "notified" state
//      is `true`.
//   * `Notify()` to set the notification's "notified" state to `true` and
//     notify all waiting threads that the event has occurred.
//     This method may only be called once.
//
// Note that while `Notify()` may only be called once, it is perfectly valid to
// call any of the `WaitForNotification*()` methods multiple times, from
// multiple threads -- even after the notification's "notified" state has been
// set -- in which case those methods will immediately return.
//
// Note that the lifetime of a `Notification` requires careful consideration;
// it might not be safe to destroy a notification after calling `Notify()` since
// it is still legal for other threads to call `WaitForNotification*()` methods
// on the notification. However, observers responding to a "notified" state of
// `true` can safely delete the notification without interfering with the call
// to `Notify()` in the other thread.
//
// Memory ordering: For any threads X and Y, if X calls `Notify()`, then any
// action taken by X before it calls `Notify()` is visible to thread Y after:
//  * Y returns from `WaitForNotification()`, or
//  * Y receives a `true` return value from `HasBeenNotified()`.
#ifdef __linux__
class Notification {
 public:
  Notification() : state_(NOT_NOTIFIED_NO_WAITERS) {}
  ~Notification() = default;

  bool HasBeenNotified() const {
    return base::subtle::Acquire_Load(&state_) == NOTIFIED;
  }

  void WaitForNotification() const {
    while (true) {
      auto s = base::subtle::Acquire_Load(&state_);
      if (s == NOT_NOTIFIED_NO_WAITERS) {
        s = base::subtle::Acquire_CompareAndSwap(
            &state_, NOT_NOTIFIED_NO_WAITERS, NOT_NOTIFIED_HAS_WAITERS);
        if (s == NOT_NOTIFIED_NO_WAITERS) {
          // We succeeded in the CAS -- sets 's' to be the new value of the
          // state rather than the previous value.
          s = NOT_NOTIFIED_HAS_WAITERS;
        }
      }
      if (s == NOTIFIED) return;
      DCHECK_EQ(s, NOT_NOTIFIED_HAS_WAITERS);
      sys_futex(&state_, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, NOT_NOTIFIED_HAS_WAITERS,
          /* timeout */ nullptr, nullptr /* ignored */, 0 /* ignored */);
    }
  }

  void Notify() {
    auto s = base::subtle::Release_AtomicExchange(&state_, NOTIFIED);
    DCHECK_NE(s, NOTIFIED) << "may only notify once";
    if (s == NOT_NOTIFIED_HAS_WAITERS) {
      sys_futex(&state_, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, INT_MAX,
          nullptr /* ignored */, nullptr /* ignored */, 0 /* ignored */);
    }
  }

 private:
  enum {
    NOT_NOTIFIED_NO_WAITERS = 1,
    NOT_NOTIFIED_HAS_WAITERS = 2,
    NOTIFIED = 3
  };
  mutable Atomic32 state_;

  DISALLOW_COPY_AND_ASSIGN(Notification);
};
#else
// macOS doesn't have futex, so we just use the mutex-based latch instead.
class Notification {
 public:
  Notification() : latch_(1) { }
  ~Notification() = default;

  bool HasBeenNotified() const {
    return latch_.count() == 0;
  }

  void WaitForNotification() const {
    latch_.Wait();
  }

  void Notify() {
    latch_.CountDown();
  }

 private:
  mutable CountDownLatch latch_;

  DISALLOW_COPY_AND_ASSIGN(Notification);
};

#endif
} // namespace kudu
