< prev index next >

src/share/vm/runtime/thread.hpp

Print this page




  25 #ifndef SHARE_VM_RUNTIME_THREAD_HPP
  26 #define SHARE_VM_RUNTIME_THREAD_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "memory/threadLocalAllocBuffer.hpp"
  30 #include "oops/oop.hpp"
  31 #include "prims/jni.h"
  32 #include "prims/jvmtiExport.hpp"
  33 #include "runtime/frame.hpp"
  34 #include "runtime/javaFrameAnchor.hpp"
  35 #include "runtime/jniHandles.hpp"
  36 #include "runtime/mutexLocker.hpp"
  37 #include "runtime/os.hpp"
  38 #include "runtime/osThread.hpp"
  39 #include "runtime/park.hpp"
  40 #include "runtime/safepoint.hpp"
  41 #include "runtime/stubRoutines.hpp"
  42 #include "runtime/threadLocalStorage.hpp"
  43 #include "runtime/thread_ext.hpp"
  44 #include "runtime/unhandledOops.hpp"
  45 #include "trace/traceBackend.hpp"
  46 #include "trace/traceMacros.hpp"
  47 #include "utilities/exceptions.hpp"
  48 #include "utilities/macros.hpp"
  49 #include "utilities/top.hpp"
  50 #if INCLUDE_ALL_GCS
  51 #include "gc_implementation/g1/dirtyCardQueue.hpp"
  52 #include "gc_implementation/g1/satbQueue.hpp"
  53 #endif // INCLUDE_ALL_GCS
  54 #ifdef TARGET_ARCH_zero
  55 # include "stack_zero.hpp"
  56 #endif



  57 
  58 class ThreadSafepointState;
  59 class ThreadProfiler;
  60 
  61 class JvmtiThreadState;
  62 class JvmtiGetLoadedClassesClosure;
  63 class ThreadStatistics;
  64 class ConcurrentLocksDump;
  65 class ParkEvent;
  66 class Parker;
  67 
  68 class ciEnv;
  69 class CompileThread;
  70 class CompileLog;
  71 class CompileTask;
  72 class CompileQueue;
  73 class CompilerCounters;
  74 class vframeArray;
  75 
  76 class DeoptResourceMark;


 178   // osThread.hpp).
 179   //
 180   // 2. It would be more natural if set_external_suspend() is private and
 181   // part of java_suspend(), but that probably would affect the suspend/query
 182   // performance. Need more investigation on this.
 183   //
 184 
 185   // suspend/resume lock: used for self-suspend
 186   Monitor* _SR_lock;
 187 
 188  protected:
 189   enum SuspendFlags {
 190     // NOTE: avoid using the sign-bit as cc generates different test code
 191     //       when the sign-bit is used, and sometimes incorrectly - see CR 6398077
 192 
 193     _external_suspend       = 0x20000000U, // thread is asked to self suspend
 194     _ext_suspended          = 0x40000000U, // thread has self-suspended
 195     _deopt_suspend          = 0x10000000U, // thread needs to self suspend for deopt
 196 
 197     _has_async_exception    = 0x00000001U, // there is a pending async exception
 198     _critical_native_unlock = 0x00000002U  // Must call back to unlock JNI critical lock


 199   };
 200 
 201   // various suspension related flags - atomically updated
 202   // overloaded for async exception checking in check_special_condition_for_native_trans.
 203   volatile uint32_t _suspend_flags;
 204 
 205  private:
 206   int _num_nested_signal;
 207 
 208  public:
 209   void enter_signal_handler() { _num_nested_signal++; }
 210   void leave_signal_handler() { _num_nested_signal--; }
 211   bool is_inside_signal_handler() const { return _num_nested_signal > 0; }
 212 
 213  private:
 214   // Debug tracing
 215   static void trace(const char* msg, const Thread* const thread) PRODUCT_RETURN;
 216 
 217   // Active_handles points to a block of handles
 218   JNIHandleBlock* _active_handles;


 243   //
 244   NOT_PRODUCT(int _allow_safepoint_count;)      // If 0, thread allow a safepoint to happen
 245   debug_only (int _allow_allocation_count;)     // If 0, the thread is allowed to allocate oops.
 246 
 247   // Used by SkipGCALot class.
 248   NOT_PRODUCT(bool _skip_gcalot;)               // Should we elide gc-a-lot?
 249 
 250   friend class No_Alloc_Verifier;
 251   friend class No_Safepoint_Verifier;
 252   friend class Pause_No_Safepoint_Verifier;
 253   friend class ThreadLocalStorage;
 254   friend class GC_locker;
 255 
 256   ThreadLocalAllocBuffer _tlab;                 // Thread-local eden
 257   jlong _allocated_bytes;                       // Cumulative number of bytes allocated on
 258                                                 // the Java heap
 259 
 260   // Thread-local buffer used by MetadataOnStackMark.
 261   MetadataOnStackBuffer* _metadata_on_stack_buffer;
 262 
 263   TRACE_DATA _trace_data;                       // Thread-local data for tracing
 264 
 265   ThreadExt _ext;
 266 
 267   int   _vm_operation_started_count;            // VM_Operation support
 268   int   _vm_operation_completed_count;          // VM_Operation support
 269 
 270   ObjectMonitor* _current_pending_monitor;      // ObjectMonitor this thread
 271                                                 // is waiting to lock
 272   bool _current_pending_monitor_is_from_java;   // locking is from Java code
 273 
 274   // ObjectMonitor on which this thread called Object.wait()
 275   ObjectMonitor* _current_waiting_monitor;
 276 
 277   // Private thread-local objectmonitor list - a simple cache organized as a SLL.
 278  public:
 279   ObjectMonitor* omFreeList;
 280   int omFreeCount;                              // length of omFreeList
 281   int omFreeProvision;                          // reload chunk size
 282   ObjectMonitor* omInUseList;                   // SLL to track monitors in circulation
 283   int omInUseCount;                             // length of omInUseList


 424   // Internal handle support
 425   HandleArea* handle_area() const                { return _handle_area; }
 426   void set_handle_area(HandleArea* area)         { _handle_area = area; }
 427 
 428   GrowableArray<Metadata*>* metadata_handles() const          { return _metadata_handles; }
 429   void set_metadata_handles(GrowableArray<Metadata*>* handles){ _metadata_handles = handles; }
 430 
 431   // Thread-Local Allocation Buffer (TLAB) support
 432   ThreadLocalAllocBuffer& tlab()                 { return _tlab; }
 433   void initialize_tlab() {
 434     if (UseTLAB) {
 435       tlab().initialize();
 436     }
 437   }
 438 
 439   jlong allocated_bytes()               { return _allocated_bytes; }
 440   void set_allocated_bytes(jlong value) { _allocated_bytes = value; }
 441   void incr_allocated_bytes(jlong size) { _allocated_bytes += size; }
 442   inline jlong cooked_allocated_bytes();
 443 
 444   TRACE_DATA* trace_data()              { return &_trace_data; }

 445 
 446   const ThreadExt& ext() const          { return _ext; }
 447   ThreadExt& ext()                      { return _ext; }
 448 
 449   // VM operation support
 450   int vm_operation_ticket()                      { return ++_vm_operation_started_count; }
 451   int vm_operation_completed_count()             { return _vm_operation_completed_count; }
 452   void increment_vm_operation_completed_count()  { _vm_operation_completed_count++; }
 453 
 454   // For tracking the heavyweight monitor the thread is pending on.
 455   ObjectMonitor* current_pending_monitor() {
 456     return _current_pending_monitor;
 457   }
 458   void set_current_pending_monitor(ObjectMonitor* monitor) {
 459     _current_pending_monitor = monitor;
 460   }
 461   void set_current_pending_monitor_is_from_java(bool from_java) {
 462     _current_pending_monitor_is_from_java = from_java;
 463   }
 464   bool current_pending_monitor_is_from_java() {


 609   static ByteSize stack_base_offset()            { return byte_offset_of(Thread, _stack_base ); }
 610   static ByteSize stack_size_offset()            { return byte_offset_of(Thread, _stack_size ); }
 611 
 612 #define TLAB_FIELD_OFFSET(name) \
 613   static ByteSize tlab_##name##_offset()         { return byte_offset_of(Thread, _tlab) + ThreadLocalAllocBuffer::name##_offset(); }
 614 
 615   TLAB_FIELD_OFFSET(start)
 616   TLAB_FIELD_OFFSET(end)
 617   TLAB_FIELD_OFFSET(top)
 618   TLAB_FIELD_OFFSET(pf_top)
 619   TLAB_FIELD_OFFSET(size)                   // desired_size
 620   TLAB_FIELD_OFFSET(refill_waste_limit)
 621   TLAB_FIELD_OFFSET(number_of_refills)
 622   TLAB_FIELD_OFFSET(fast_refill_waste)
 623   TLAB_FIELD_OFFSET(slow_allocations)
 624 
 625 #undef TLAB_FIELD_OFFSET
 626 
 627   static ByteSize allocated_bytes_offset()       { return byte_offset_of(Thread, _allocated_bytes ); }
 628 


 629  public:
 630   volatile intptr_t _Stalled ;
 631   volatile int _TypeTag ;
 632   ParkEvent * _ParkEvent ;                     // for synchronized()
 633   ParkEvent * _SleepEvent ;                    // for Thread.sleep
 634   ParkEvent * _MutexEvent ;                    // for native internal Mutex/Monitor
 635   ParkEvent * _MuxEvent ;                      // for low-level muxAcquire-muxRelease
 636   int NativeSyncRecursion ;                    // diagnostic
 637 
 638   volatile int _OnTrap ;                       // Resume-at IP delta
 639   jint _hashStateW ;                           // Marsaglia Shift-XOR thread-local RNG
 640   jint _hashStateX ;                           // thread-specific hashCode generator state
 641   jint _hashStateY ;
 642   jint _hashStateZ ;
 643   void * _schedctl ;
 644 
 645 
 646   volatile jint rng [4] ;                      // RNG for spin loop
 647 
 648   // Low-level leaf-lock primitives used to implement synchronization


 711   virtual WorkerThread* as_Worker_thread() const {
 712     assert(is_Worker_thread(), "Dubious cast to WorkerThread*?");
 713     return (WorkerThread*) this;
 714   }
 715 
 716   void set_id(uint work_id)             { _id = work_id; }
 717   uint id() const                       { return _id; }
 718 };
 719 
 720 // A single WatcherThread is used for simulating timer interrupts.
 721 class WatcherThread: public Thread {
 722   friend class VMStructs;
 723  public:
 724   virtual void run();
 725 
 726  private:
 727   static WatcherThread* _watcher_thread;
 728 
 729   static bool _startable;
 730   volatile static bool _should_terminate; // updated without holding lock
 731 
 732   os::WatcherThreadCrashProtection* _crash_protection;
 733  public:
 734   enum SomeConstants {
 735     delay_interval = 10                          // interrupt delay in milliseconds
 736   };
 737 
 738   // Constructor
 739   WatcherThread();
 740 
 741   // Tester
 742   bool is_Watcher_thread() const                 { return true; }
 743 
 744   // Printing
 745   char* name() const { return (char*)"VM Periodic Task Thread"; }
 746   void print_on(outputStream* st) const;
 747   void print() const { print_on(tty); }
 748   void unpark();
 749 
 750   // Returns the single instance of WatcherThread
 751   static WatcherThread* watcher_thread()         { return _watcher_thread; }
 752 
 753   // Create and start the single instance of WatcherThread, or stop it on shutdown
 754   static void start();
 755   static void stop();
 756   // Only allow start once the VM is sufficiently initialized
 757   // Otherwise the first task to enroll will trigger the start
 758   static void make_startable();
 759 
 760   void set_crash_protection(os::WatcherThreadCrashProtection* crash_protection) {
 761     assert(Thread::current()->is_Watcher_thread(), "Can only be set by WatcherThread");
 762     _crash_protection = crash_protection;
 763   }
 764 
 765   bool has_crash_protection() const { return _crash_protection != NULL; }
 766   os::WatcherThreadCrashProtection* crash_protection() const { return _crash_protection; }
 767 
 768  private:
 769   int sleep() const;
 770 };
 771 
 772 
 773 class CompilerThread;
 774 
 775 typedef void (*ThreadFunction)(JavaThread*, TRAPS);
 776 
 777 class JavaThread: public Thread {
 778   friend class VMStructs;
 779  private:
 780   JavaThread*    _next;                          // The next thread in the Threads list
 781   oop            _threadObj;                     // The Java level thread object
 782 
 783 #ifdef ASSERT
 784  private:
 785   int _java_call_counter;
 786 
 787  public:




  25 #ifndef SHARE_VM_RUNTIME_THREAD_HPP
  26 #define SHARE_VM_RUNTIME_THREAD_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "memory/threadLocalAllocBuffer.hpp"
  30 #include "oops/oop.hpp"
  31 #include "prims/jni.h"
  32 #include "prims/jvmtiExport.hpp"
  33 #include "runtime/frame.hpp"
  34 #include "runtime/javaFrameAnchor.hpp"
  35 #include "runtime/jniHandles.hpp"
  36 #include "runtime/mutexLocker.hpp"
  37 #include "runtime/os.hpp"
  38 #include "runtime/osThread.hpp"
  39 #include "runtime/park.hpp"
  40 #include "runtime/safepoint.hpp"
  41 #include "runtime/stubRoutines.hpp"
  42 #include "runtime/threadLocalStorage.hpp"
  43 #include "runtime/thread_ext.hpp"
  44 #include "runtime/unhandledOops.hpp"


  45 #include "utilities/exceptions.hpp"
  46 #include "utilities/macros.hpp"
  47 #include "utilities/top.hpp"
  48 #if INCLUDE_ALL_GCS
  49 #include "gc_implementation/g1/dirtyCardQueue.hpp"
  50 #include "gc_implementation/g1/satbQueue.hpp"
  51 #endif // INCLUDE_ALL_GCS
  52 #ifdef TARGET_ARCH_zero
  53 # include "stack_zero.hpp"
  54 #endif
  55 #if INCLUDE_JFR
  56 #include "jfr/support/jfrThreadExtension.hpp"
  57 #endif
  58 
  59 class ThreadSafepointState;
  60 class ThreadProfiler;
  61 
  62 class JvmtiThreadState;
  63 class JvmtiGetLoadedClassesClosure;
  64 class ThreadStatistics;
  65 class ConcurrentLocksDump;
  66 class ParkEvent;
  67 class Parker;
  68 
  69 class ciEnv;
  70 class CompileThread;
  71 class CompileLog;
  72 class CompileTask;
  73 class CompileQueue;
  74 class CompilerCounters;
  75 class vframeArray;
  76 
  77 class DeoptResourceMark;


 179   // osThread.hpp).
 180   //
 181   // 2. It would be more natural if set_external_suspend() is private and
 182   // part of java_suspend(), but that probably would affect the suspend/query
 183   // performance. Need more investigation on this.
 184   //
 185 
 186   // suspend/resume lock: used for self-suspend
 187   Monitor* _SR_lock;
 188 
 189  protected:
 190   enum SuspendFlags {
 191     // NOTE: avoid using the sign-bit as cc generates different test code
 192     //       when the sign-bit is used, and sometimes incorrectly - see CR 6398077
 193 
 194     _external_suspend       = 0x20000000U, // thread is asked to self suspend
 195     _ext_suspended          = 0x40000000U, // thread has self-suspended
 196     _deopt_suspend          = 0x10000000U, // thread needs to self suspend for deopt
 197 
 198     _has_async_exception    = 0x00000001U, // there is a pending async exception
 199     _critical_native_unlock = 0x00000002U, // Must call back to unlock JNI critical lock
 200 
 201     JFR_ONLY(_trace_flag    = 0x00000004U)  // call jfr tracing
 202   };
 203 
 204   // various suspension related flags - atomically updated
 205   // overloaded for async exception checking in check_special_condition_for_native_trans.
 206   volatile uint32_t _suspend_flags;
 207 
 208  private:
 209   int _num_nested_signal;
 210 
 211  public:
 212   void enter_signal_handler() { _num_nested_signal++; }
 213   void leave_signal_handler() { _num_nested_signal--; }
 214   bool is_inside_signal_handler() const { return _num_nested_signal > 0; }
 215 
 216  private:
 217   // Debug tracing
 218   static void trace(const char* msg, const Thread* const thread) PRODUCT_RETURN;
 219 
 220   // Active_handles points to a block of handles
 221   JNIHandleBlock* _active_handles;


 246   //
 247   NOT_PRODUCT(int _allow_safepoint_count;)      // If 0, thread allow a safepoint to happen
 248   debug_only (int _allow_allocation_count;)     // If 0, the thread is allowed to allocate oops.
 249 
 250   // Used by SkipGCALot class.
 251   NOT_PRODUCT(bool _skip_gcalot;)               // Should we elide gc-a-lot?
 252 
 253   friend class No_Alloc_Verifier;
 254   friend class No_Safepoint_Verifier;
 255   friend class Pause_No_Safepoint_Verifier;
 256   friend class ThreadLocalStorage;
 257   friend class GC_locker;
 258 
 259   ThreadLocalAllocBuffer _tlab;                 // Thread-local eden
 260   jlong _allocated_bytes;                       // Cumulative number of bytes allocated on
 261                                                 // the Java heap
 262 
 263   // Thread-local buffer used by MetadataOnStackMark.
 264   MetadataOnStackBuffer* _metadata_on_stack_buffer;
 265 
 266   JFR_ONLY(DEFINE_THREAD_LOCAL_FIELD_JFR;)      // Thread-local data for jfr
 267 
 268   ThreadExt _ext;
 269 
 270   int   _vm_operation_started_count;            // VM_Operation support
 271   int   _vm_operation_completed_count;          // VM_Operation support
 272 
 273   ObjectMonitor* _current_pending_monitor;      // ObjectMonitor this thread
 274                                                 // is waiting to lock
 275   bool _current_pending_monitor_is_from_java;   // locking is from Java code
 276 
 277   // ObjectMonitor on which this thread called Object.wait()
 278   ObjectMonitor* _current_waiting_monitor;
 279 
 280   // Private thread-local objectmonitor list - a simple cache organized as a SLL.
 281  public:
 282   ObjectMonitor* omFreeList;
 283   int omFreeCount;                              // length of omFreeList
 284   int omFreeProvision;                          // reload chunk size
 285   ObjectMonitor* omInUseList;                   // SLL to track monitors in circulation
 286   int omInUseCount;                             // length of omInUseList


 427   // Internal handle support
 428   HandleArea* handle_area() const                { return _handle_area; }
 429   void set_handle_area(HandleArea* area)         { _handle_area = area; }
 430 
 431   GrowableArray<Metadata*>* metadata_handles() const          { return _metadata_handles; }
 432   void set_metadata_handles(GrowableArray<Metadata*>* handles){ _metadata_handles = handles; }
 433 
 434   // Thread-Local Allocation Buffer (TLAB) support
 435   ThreadLocalAllocBuffer& tlab()                 { return _tlab; }
 436   void initialize_tlab() {
 437     if (UseTLAB) {
 438       tlab().initialize();
 439     }
 440   }
 441 
 442   jlong allocated_bytes()               { return _allocated_bytes; }
 443   void set_allocated_bytes(jlong value) { _allocated_bytes = value; }
 444   void incr_allocated_bytes(jlong size) { _allocated_bytes += size; }
 445   inline jlong cooked_allocated_bytes();
 446 
 447   JFR_ONLY(DEFINE_THREAD_LOCAL_ACCESSOR_JFR;)
 448   JFR_ONLY(DEFINE_TRACE_SUSPEND_FLAG_METHODS)
 449 
 450   const ThreadExt& ext() const          { return _ext; }
 451   ThreadExt& ext()                      { return _ext; }
 452 
 453   // VM operation support
 454   int vm_operation_ticket()                      { return ++_vm_operation_started_count; }
 455   int vm_operation_completed_count()             { return _vm_operation_completed_count; }
 456   void increment_vm_operation_completed_count()  { _vm_operation_completed_count++; }
 457 
 458   // For tracking the heavyweight monitor the thread is pending on.
 459   ObjectMonitor* current_pending_monitor() {
 460     return _current_pending_monitor;
 461   }
 462   void set_current_pending_monitor(ObjectMonitor* monitor) {
 463     _current_pending_monitor = monitor;
 464   }
 465   void set_current_pending_monitor_is_from_java(bool from_java) {
 466     _current_pending_monitor_is_from_java = from_java;
 467   }
 468   bool current_pending_monitor_is_from_java() {


 613   static ByteSize stack_base_offset()            { return byte_offset_of(Thread, _stack_base ); }
 614   static ByteSize stack_size_offset()            { return byte_offset_of(Thread, _stack_size ); }
 615 
 616 #define TLAB_FIELD_OFFSET(name) \
 617   static ByteSize tlab_##name##_offset()         { return byte_offset_of(Thread, _tlab) + ThreadLocalAllocBuffer::name##_offset(); }
 618 
 619   TLAB_FIELD_OFFSET(start)
 620   TLAB_FIELD_OFFSET(end)
 621   TLAB_FIELD_OFFSET(top)
 622   TLAB_FIELD_OFFSET(pf_top)
 623   TLAB_FIELD_OFFSET(size)                   // desired_size
 624   TLAB_FIELD_OFFSET(refill_waste_limit)
 625   TLAB_FIELD_OFFSET(number_of_refills)
 626   TLAB_FIELD_OFFSET(fast_refill_waste)
 627   TLAB_FIELD_OFFSET(slow_allocations)
 628 
 629 #undef TLAB_FIELD_OFFSET
 630 
 631   static ByteSize allocated_bytes_offset()       { return byte_offset_of(Thread, _allocated_bytes ); }
 632 
 633   JFR_ONLY(DEFINE_THREAD_LOCAL_OFFSET_JFR;)
 634 
 635  public:
 636   volatile intptr_t _Stalled ;
 637   volatile int _TypeTag ;
 638   ParkEvent * _ParkEvent ;                     // for synchronized()
 639   ParkEvent * _SleepEvent ;                    // for Thread.sleep
 640   ParkEvent * _MutexEvent ;                    // for native internal Mutex/Monitor
 641   ParkEvent * _MuxEvent ;                      // for low-level muxAcquire-muxRelease
 642   int NativeSyncRecursion ;                    // diagnostic
 643 
 644   volatile int _OnTrap ;                       // Resume-at IP delta
 645   jint _hashStateW ;                           // Marsaglia Shift-XOR thread-local RNG
 646   jint _hashStateX ;                           // thread-specific hashCode generator state
 647   jint _hashStateY ;
 648   jint _hashStateZ ;
 649   void * _schedctl ;
 650 
 651 
 652   volatile jint rng [4] ;                      // RNG for spin loop
 653 
 654   // Low-level leaf-lock primitives used to implement synchronization


 717   virtual WorkerThread* as_Worker_thread() const {
 718     assert(is_Worker_thread(), "Dubious cast to WorkerThread*?");
 719     return (WorkerThread*) this;
 720   }
 721 
 722   void set_id(uint work_id)             { _id = work_id; }
 723   uint id() const                       { return _id; }
 724 };
 725 
 726 // A single WatcherThread is used for simulating timer interrupts.
 727 class WatcherThread: public Thread {
 728   friend class VMStructs;
 729  public:
 730   virtual void run();
 731 
 732  private:
 733   static WatcherThread* _watcher_thread;
 734 
 735   static bool _startable;
 736   volatile static bool _should_terminate; // updated without holding lock


 737  public:
 738   enum SomeConstants {
 739     delay_interval = 10                          // interrupt delay in milliseconds
 740   };
 741 
 742   // Constructor
 743   WatcherThread();
 744 
 745   // Tester
 746   bool is_Watcher_thread() const                 { return true; }
 747 
 748   // Printing
 749   char* name() const { return (char*)"VM Periodic Task Thread"; }
 750   void print_on(outputStream* st) const;
 751   void print() const { print_on(tty); }
 752   void unpark();
 753 
 754   // Returns the single instance of WatcherThread
 755   static WatcherThread* watcher_thread()         { return _watcher_thread; }
 756 
 757   // Create and start the single instance of WatcherThread, or stop it on shutdown
 758   static void start();
 759   static void stop();
 760   // Only allow start once the VM is sufficiently initialized
 761   // Otherwise the first task to enroll will trigger the start
 762   static void make_startable();









 763  private:
 764   int sleep() const;
 765 };
 766 
 767 
 768 class CompilerThread;
 769 
 770 typedef void (*ThreadFunction)(JavaThread*, TRAPS);
 771 
 772 class JavaThread: public Thread {
 773   friend class VMStructs;
 774  private:
 775   JavaThread*    _next;                          // The next thread in the Threads list
 776   oop            _threadObj;                     // The Java level thread object
 777 
 778 #ifdef ASSERT
 779  private:
 780   int _java_call_counter;
 781 
 782  public:


< prev index next >