/*
 * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_CLASSFILE_PLACEHOLDERS_HPP
#define SHARE_CLASSFILE_PLACEHOLDERS_HPP

#include "oops/symbolHandle.hpp"

class PlaceholderEntry;
class Thread;
class ClassLoaderData;

// Placeholder objects. These represent classes currently
// being loaded, as well as arrays of primitives.
//

class PlaceholderTable : public AllStatic {
 public:
  // caller to create a placeholder entry must enumerate an action
  // caller claims ownership of that action
  // For parallel classloading:
  // multiple LOAD_INSTANCE threads can proceed in parallel
  // multiple LOAD_SUPER threads can proceed in parallel
  // LOAD_SUPER needed to check for class circularity
  // DEFINE_CLASS: ultimately define class must be single threaded
  // on a class/classloader basis
  // so the head of that queue owns the token
  // and the rest of the threads return the result the first thread gets
  enum classloadAction {
    LOAD_INSTANCE = 1,             // calling load_instance_class
    LOAD_SUPER = 2,                // loading superclass for this class
    DEFINE_CLASS = 3               // find_or_define class
  };
  static void initialize();
  static PlaceholderEntry* get_entry(Symbol* name, ClassLoaderData* loader_data);

  // find_and_add returns probe pointer - old or new
  // If no entry exists, add a placeholder entry and push SeenThread for classloadAction
  // If entry exists, reuse entry and push SeenThread for classloadAction
  static PlaceholderEntry* find_and_add(Symbol* name, ClassLoaderData* loader_data,
                                        classloadAction action, Symbol* supername,
                                        JavaThread* thread);

  // find_and_remove first removes SeenThread for classloadAction
  // If all queues are empty and definer is null, remove the PlacheholderEntry completely
  static void find_and_remove(Symbol* name, ClassLoaderData* loader_data,
                       classloadAction action, JavaThread* thread);

  static void print_on(outputStream* st);
  static void print();
};

class SeenThread;

// Placeholder objects represent classes currently being loaded.
// All threads examining the placeholder table must hold the
// SystemDictionary_lock, so we don't need special precautions
// on store ordering here.
// The system dictionary is the only user of this class.
class PlaceholderEntry {
  friend class PlaceholderTable;
 private:
  SymbolHandle      _supername;
  JavaThread*       _definer;       // owner of define token
  InstanceKlass*    _instanceKlass; // InstanceKlass from successful define
  SeenThread*       _superThreadQ;  // doubly-linked queue of Threads loading a superclass for this class
  SeenThread*       _loadInstanceThreadQ;  // loadInstance thread
                                    // This can't be multiple threads since class loading waits for
                                    // this token to be removed.

  SeenThread*       _defineThreadQ; // queue of Threads trying to define this class
                                    // including _definer
                                    // _definer owns token
                                    // queue waits for and returns results from _definer

  SeenThread* actionToQueue(PlaceholderTable::classloadAction action);
  void set_threadQ(SeenThread* seenthread, PlaceholderTable::classloadAction action);
  void add_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);
  bool remove_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);

  SeenThread*        superThreadQ()        const { return _superThreadQ; }
  void               set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; }

  SeenThread*        loadInstanceThreadQ() const { return _loadInstanceThreadQ; }
  void               set_loadInstanceThreadQ(SeenThread* SeenThread) { _loadInstanceThreadQ = SeenThread; }

  SeenThread*        defineThreadQ()       const { return _defineThreadQ; }
  void               set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }
 public:
  PlaceholderEntry() :
     _definer(nullptr), _instanceKlass(nullptr),
     _superThreadQ(nullptr), _loadInstanceThreadQ(nullptr), _defineThreadQ(nullptr) { }

  Symbol*            supername()           const { return _supername; }
  void               set_supername(Symbol* supername);

  JavaThread*        definer()             const {return _definer; }
  void               set_definer(JavaThread* definer) { _definer = definer; }

  InstanceKlass*     instance_klass()      const {return _instanceKlass; }
  void               set_instance_klass(InstanceKlass* ik) { _instanceKlass = ik; }

  bool super_load_in_progress() {
     return (_superThreadQ != nullptr);
  }

  bool instance_load_in_progress() {
    return (_loadInstanceThreadQ != nullptr);
  }

  bool define_class_in_progress() {
    return (_defineThreadQ != nullptr);
  }

  // Used for ClassCircularityError checking
  bool check_seen_thread(JavaThread* thread, PlaceholderTable::classloadAction action);

  void print_on(outputStream* st) const;
};

#endif // SHARE_CLASSFILE_PLACEHOLDERS_HPP
