// Copyright (C) 2019-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

// { dg-options "-std=gnu++2a -pthread" }
// { dg-do run { target c++2a } }
// { dg-add-options libatomic }
// { dg-additional-options "-pthread" { target pthread } }
// { dg-require-gthreads "" }

#include <thread>
#include <chrono>
#include <atomic>
#include <testsuite_hooks.h>

using namespace std::literals;

//------------------------------------------------------

void test_no_stop_token()
{
  // test the basic jthread API (not taking stop_token arg)

  VERIFY(std::jthread::hardware_concurrency() == std::thread::hardware_concurrency());
  std::stop_token stoken;
  VERIFY(!stoken.stop_possible());
  {
    std::jthread::id t1ID{std::this_thread::get_id()};
    std::atomic<bool> t1AllSet{false};
    std::jthread t1([&t1ID, &t1AllSet] {
                   t1ID = std::this_thread::get_id();
                   t1AllSet.store(true);
                   for (int c='9'; c>='0'; --c) {
                      std::this_thread::sleep_for(222ms);
                   }
                 });
    for (int i=0; !t1AllSet.load(); ++i) {
      std::this_thread::sleep_for(10ms);
    }
    VERIFY(t1.joinable());
    VERIFY(t1ID == t1.get_id());
    stoken = t1.get_stop_token();
    VERIFY(!stoken.stop_requested());
  }
  VERIFY(stoken.stop_requested());
}

//------------------------------------------------------

void test_stop_token()
{
  // test the basic thread API (taking stop_token arg)

  std::stop_source ssource;
  std::stop_source origsource;
  VERIFY(ssource.stop_possible());
  VERIFY(!ssource.stop_requested());
  {
    std::jthread::id t1ID{std::this_thread::get_id()};
    std::atomic<bool> t1AllSet{false};
    std::atomic<bool> t1done{false};
    std::jthread t1([&t1ID, &t1AllSet, &t1done] (std::stop_token st) {
                       // check some values of the started thread:
                       t1ID = std::this_thread::get_id();
                       t1AllSet.store(true);
                       for (int i=0; !st.stop_requested(); ++i) {
                          std::this_thread::sleep_for(100ms);
                       }
                       t1done.store(true);
                     },
                     ssource.get_token());
    for (int i=0; !t1AllSet.load(); ++i) {
      std::this_thread::sleep_for(10ms);
    }
    // and check all values:
    VERIFY(t1.joinable());
    VERIFY(t1ID == t1.get_id());

    std::this_thread::sleep_for(470ms);
    origsource = std::move(ssource);
    ssource = t1.get_stop_source();
    VERIFY(!ssource.stop_requested());
    auto ret = ssource.request_stop();
    VERIFY(ret);
    ret = ssource.request_stop();
    VERIFY(!ret);
    VERIFY(ssource.stop_requested());
    VERIFY(!t1done.load());
    VERIFY(!origsource.stop_requested());

    std::this_thread::sleep_for(470ms);
    origsource.request_stop();
  }
  VERIFY(origsource.stop_requested());
  VERIFY(ssource.stop_requested());
}

//------------------------------------------------------

void test_join()
{
  std::stop_source ssource;
  VERIFY(ssource.stop_possible());
  {
    std::jthread t1([](std::stop_token stoken) {
                      for (int i=0; !stoken.stop_requested(); ++i) {
                         std::this_thread::sleep_for(100ms);
                      }
                 });
    ssource = t1.get_stop_source();
    std::jthread t2([ssource] () mutable {
                     for (int i=0; i < 10; ++i) {
                       std::this_thread::sleep_for(70ms);
                     }
                     ssource.request_stop();
                   });
    // wait for all thread to finish:
    t2.join();
    VERIFY(!t2.joinable());
    VERIFY(t1.joinable());
    t1.join();
    VERIFY(!t1.joinable());
  }
}

//------------------------------------------------------

void test_detach()
{
  std::stop_source ssource;
  VERIFY(ssource.stop_possible());
  std::atomic<bool> t1FinallyInterrupted{false};
  {
    std::jthread t0;
    std::jthread::id t1ID{std::this_thread::get_id()};
    bool t1IsInterrupted;
    std::stop_token t1InterruptToken;
    std::atomic<bool> t1AllSet{false};
    std::jthread t1([&t1ID, &t1IsInterrupted, &t1InterruptToken, &t1AllSet, &t1FinallyInterrupted]
                    (std::stop_token stoken) {
                   // check some values of the started thread:
                   t1ID = std::this_thread::get_id();
                   t1InterruptToken = stoken;
                   t1IsInterrupted = stoken.stop_requested();
                   VERIFY(stoken.stop_possible());
                   VERIFY(!stoken.stop_requested());
                   t1AllSet.store(true);
                   for (int i=0; !stoken.stop_requested(); ++i) {
                      std::this_thread::sleep_for(100ms);
                   }
                   t1FinallyInterrupted.store(true);
                 });
    for (int i=0; !t1AllSet.load(); ++i) {
      std::this_thread::sleep_for(10ms);
    }
    VERIFY(!t0.joinable());
    VERIFY(t1.joinable());
    VERIFY(t1ID == t1.get_id());
    VERIFY(t1IsInterrupted == false);
    VERIFY(t1InterruptToken == t1.get_stop_source().get_token());
    ssource = t1.get_stop_source();
    VERIFY(t1InterruptToken.stop_possible());
    VERIFY(!t1InterruptToken.stop_requested());
    t1.detach();
    VERIFY(!t1.joinable());
  }

  VERIFY(!t1FinallyInterrupted.load());
  ssource.request_stop();
  VERIFY(ssource.stop_requested());
  for (int i=0; !t1FinallyInterrupted.load() && i < 100; ++i) {
    std::this_thread::sleep_for(100ms);
  }
  VERIFY(t1FinallyInterrupted.load());
}

//------------------------------------------------------

void test_move_assignment()
{
    std::jthread thread1([]{});
    std::jthread thread2([]{});

    const auto id2 = thread2.get_id();
    const auto ssource2 = thread2.get_stop_source();

    thread1 = std::move(thread2);

    VERIFY(thread1.get_id() == id2);
    VERIFY(thread2.get_id() == std::jthread::id());

    VERIFY(thread1.get_stop_source() == ssource2);
    VERIFY(!thread2.get_stop_source().stop_possible());
}

int main()
{
  std::set_terminate([](){
                       VERIFY(false);
                     });

  test_no_stop_token();
  test_stop_token();
  test_join();
  test_detach();
  test_move_assignment();
}
