Program Listing for File atomic_signalable.h

Return to documentation for file (ecal/service/test/src/atomic_signalable.h)

/* ========================= eCAL LICENSE =================================
 *
 * Copyright (C) 2016 - 2023 Continental Corporation
 *
 * Licensed 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.
 *
 * ========================= eCAL LICENSE =================================
*/

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>

template <typename T>
class atomic_signalable
{
public:
  atomic_signalable(T initial_value) : value(initial_value) {}

  atomic_signalable<T>& operator=(const T new_value)
  {
    std::lock_guard<std::mutex> lock(mutex);
    value = new_value;
    cv.notify_all();
    return *this;
  }

  T operator++()
  {
    std::lock_guard<std::mutex> lock(mutex);
    T newValue = ++value;
    cv.notify_all();
    return newValue;
  }

  T operator++(T)
  {
    std::lock_guard<std::mutex> lock(mutex);
    T oldValue = value++;
    cv.notify_all();
    return oldValue;
  }

  T operator--()
  {
    std::lock_guard<std::mutex> lock(mutex);
    T newValue = --value;
    cv.notify_all();
    return newValue;
  }

  T operator--(T)
  {
    std::lock_guard<std::mutex> lock(mutex);
    T oldValue = value--;
    cv.notify_all();
    return oldValue;
  }

  T operator+=(const T& other)
  {
    std::lock_guard<std::mutex> lock(mutex);
    value += other;
    cv.notify_all();
    return value;
  }

  T operator-=(const T& other)
  {
    std::lock_guard<std::mutex> lock(mutex);
    value -= other;
    cv.notify_all();
    return value;
  }

  T operator*=(const T& other)
  {
    std::lock_guard<std::mutex> lock(mutex);
    value *= other;
    cv.notify_all();
    return value;
  }

  T operator/=(const T& other)
  {
    std::lock_guard<std::mutex> lock(mutex);
    value /= other;
    cv.notify_all();
    return value;
  }

  T operator%=(const T& other)
  {
    std::lock_guard<std::mutex> lock(mutex);
    value %= other;
    cv.notify_all();
    return value;
  }

  template <typename Predicate>
  bool wait_for(Predicate predicate, std::chrono::milliseconds timeout)
  {
    std::unique_lock<std::mutex> lock(mutex);
    return cv.wait_for(lock, timeout, [&]() { return predicate(value); });
  }

  T get() const
  {
    std::lock_guard<std::mutex> lock(mutex);
    return value;
  }

  bool operator==(T other) const
  {
    std::lock_guard<std::mutex> lock(mutex);
    return value == other;
  }

  bool operator==(const atomic_signalable<T>& other) const
  {
    std::lock_guard<std::mutex> lock_this(mutex);
    std::lock_guard<std::mutex> lock_other(other.mutex);
    return value == other.value;
  }

  bool operator!=(T other) const
  {
    std::lock_guard<std::mutex> lock(mutex);
    return value != other;
  }

  bool operator<(T other) const
  {
    std::lock_guard<std::mutex> lock(mutex);
    return value < other;
  }

  bool operator<=(T other) const
  {
    std::lock_guard<std::mutex> lock(mutex);
    return value <= other;
  }

  bool operator>(T other) const
  {
    std::lock_guard<std::mutex> lock(mutex);
    return value > other;
  }

  bool operator>=(T other) const
  {
    std::lock_guard<std::mutex> lock(mutex);
    return value >= other;
  }

private:
  T value;
  std::condition_variable cv;
  mutable std::mutex mutex;
};


template <typename T>
bool operator==(const T& other, const atomic_signalable<T>& atomic)
{
  return atomic == other;
}

template <typename T>
bool operator!=(const T& other, const atomic_signalable<T>& atomic)
{
  return atomic != other;
}

template <typename T>
bool operator<(const T& other, const atomic_signalable<T>& atomic)
{
  return atomic > other;
}

template <typename T>
bool operator<=(const T& other, const atomic_signalable<T>& atomic)
{
  return atomic >= other;
}

template <typename T>
bool operator>(const T& other, const atomic_signalable<T>& atomic)
{
  return atomic < other;
}

template <typename T>
bool operator>=(const T& other, const atomic_signalable<T>& atomic)
{
  return atomic <= other;
}