// token.h -- lock tokens for gold   -*- C++ -*-

// Copyright (C) 2006-2021 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.

// This file is part of gold.

// This program 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 of the License, or
// (at your option) any later version.

// This program 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 program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

#ifndef GOLD_TOKEN_H
#define GOLD_TOKEN_H

namespace gold
{

class Condvar;
class Task;

// A list of Tasks, managed through the next_locked_ field in the
// class Task.  We define this class here because we need it in
// Task_token.

class Task_list
{
 public:
  Task_list()
    : head_(NULL), tail_(NULL)
  { }

  ~Task_list()
  { gold_assert(this->head_ == NULL && this->tail_ == NULL); }

  // Return whether the list is empty.
  bool
  empty() const
  { return this->head_ == NULL; }

  // Add T to the head of the list.
  void
  push_front(Task* t);

  // Add T to the end of the list.
  void
  push_back(Task* t);

  // Remove the first Task on the list and return it.  Return NULL if
  // the list is empty.
  Task*
  pop_front();

 private:
  // The start of the list.  NULL if the list is empty.
  Task* head_;
  // The end of the list.  NULL if the list is empty.
  Task* tail_;
};

// We support two basic types of locks, which are both implemented
// using the single class Task_token.

// A write lock may be held by a single Task at a time.  This is used
// to control access to a single shared resource such as an Object.

// A blocker is used to indicate that a Task A must be run after some
// set of Tasks B.  For each of the Tasks B, we increment the blocker
// when the Task is created, and decrement it when the Task is
// completed.  When the count goes to 0, the task A is ready to run.

// There are no shared read locks.  We always read and write objects
// in predictable patterns.  The purpose of the locks is to permit
// some flexibility for the threading system, for cases where the
// execution order does not matter.

// These tokens are only manipulated when the workqueue lock is held
// or when they are first created.  They do not require any locking
// themselves.

class Task_token
{
 public:
  Task_token(bool is_blocker)
    : is_blocker_(is_blocker), blockers_(0), writer_(NULL), waiting_()
  { }

  ~Task_token()
  {
    gold_assert(this->blockers_ == 0);
    gold_assert(this->writer_ == NULL);
  }

  // Return whether this is a blocker.
  bool
  is_blocker() const
  { return this->is_blocker_; }

  // A write lock token uses these methods.

  // Is the token writable?
  bool
  is_writable() const
  {
    gold_assert(!this->is_blocker_);
    return this->writer_ == NULL;
  }

  // Add the task as the token's writer (there may only be one
  // writer).
  void
  add_writer(const Task* t)
  {
    gold_assert(!this->is_blocker_ && this->writer_ == NULL);
    this->writer_ = t;
  }

  // Remove the task as the token's writer.
  void
  remove_writer(const Task* t)
  {
    gold_assert(!this->is_blocker_ && this->writer_ == t);
    this->writer_ = NULL;
  }

  // A blocker token uses these methods.

  // Add a blocker to the token.
  void
  add_blocker()
  {
    gold_assert(this->is_blocker_);
    ++this->blockers_;
    this->writer_ = NULL;
  }

  // Add some number of blockers to the token.
  void
  add_blockers(int c)
  {
    gold_assert(this->is_blocker_);
    this->blockers_ += c;
    this->writer_ = NULL;
  }

  // Remove a blocker from the token.  Returns true if block count
  // drops to zero.
  bool
  remove_blocker()
  {
    gold_assert(this->is_blocker_ && this->blockers_ > 0);
    --this->blockers_;
    this->writer_ = NULL;
    return this->blockers_ == 0;
  }

  // Is the token currently blocked?
  bool
  is_blocked() const
  {
    gold_assert(this->is_blocker_);
    return this->blockers_ > 0;
  }

  // Both blocker and write lock tokens use these methods.

  // Add T to the list of tasks waiting for this token to be released.
  void
  add_waiting(Task* t)
  { this->waiting_.push_back(t); }

  // Add T to the front of the list of tasks waiting for this token to
  // be released.
  void
  add_waiting_front(Task* t)
  { this->waiting_.push_front(t); }

  // Remove the first Task waiting for this token to be released, and
  // return it.  Return NULL if no Tasks are waiting.
  Task*
  remove_first_waiting()
  { return this->waiting_.pop_front(); }

 private:
  // It makes no sense to copy these.
  Task_token(const Task_token&);
  Task_token& operator=(const Task_token&);

  // Whether this is a blocker token.
  bool is_blocker_;
  // The number of blockers.
  int blockers_;
  // The single writer.
  const Task* writer_;
  // The list of Tasks waiting for this token to be released.
  Task_list waiting_;
};

// In order to support tokens more reliably, we provide objects which
// handle them using RAII.

// RAII class to get a write lock on a token.  This requires
// specifying the task which is doing the lock.

class Task_write_token
{
 public:
  Task_write_token(Task_token* token, const Task* task)
    : token_(token), task_(task)
  { this->token_->add_writer(this->task_); }

  ~Task_write_token()
  { this->token_->remove_writer(this->task_); }

 private:
  Task_write_token(const Task_write_token&);
  Task_write_token& operator=(const Task_write_token&);

  Task_token* token_;
  const Task* task_;
};

// RAII class for a blocker.

class Task_block_token
{
 public:
  // The blocker count must be incremented when the task is created.
  // This object is created when the task is run, so we don't do
  // anything in the constructor.
  Task_block_token(Task_token* token)
    : token_(token)
  { gold_assert(this->token_->is_blocked()); }

  ~Task_block_token()
  { this->token_->remove_blocker(); }

 private:
  Task_block_token(const Task_block_token&);
  Task_block_token& operator=(const Task_block_token&);

  Task_token* token_;
};

// An object which implements an RAII lock for any object which
// supports lock and unlock methods.

template<typename Obj>
class Task_lock_obj
{
 public:
  Task_lock_obj(const Task* task, Obj* obj)
    : task_(task), obj_(obj)
  { this->obj_->lock(task); }

  ~Task_lock_obj()
  { this->obj_->unlock(this->task_); }

 private:
  Task_lock_obj(const Task_lock_obj&);
  Task_lock_obj& operator=(const Task_lock_obj&);

  const Task* task_;
  Obj* obj_;
};

// A class which holds the set of Task_tokens which must be locked for
// a Task.  No Task requires more than four Task_tokens, so we set
// that as a limit.

class Task_locker
{
 public:
  static const int max_task_count = 4;

  Task_locker()
    : count_(0)
  { }

  ~Task_locker()
  { }

  // Clear the locker.
  void
  clear()
  { this->count_ = 0; }

  // Add a token to the locker.
  void
  add(Task* t, Task_token* token)
  {
    gold_assert(this->count_ < max_task_count);
    this->tokens_[this->count_] = token;
    ++this->count_;
    // A blocker will have been incremented when the task is created.
    // A writer we need to lock now.
    if (!token->is_blocker())
      token->add_writer(t);
  }

  // Iterate over the tokens.

  typedef Task_token** iterator;

  iterator
  begin()
  { return &this->tokens_[0]; }

  iterator
  end()
  { return &this->tokens_[this->count_]; }

 private:
  Task_locker(const Task_locker&);
  Task_locker& operator=(const Task_locker&);

  // The number of tokens.
  int count_;
  // The tokens.
  Task_token* tokens_[max_task_count];
};

} // End namespace gold.

#endif // !defined(GOLD_TOKEN_H)
