/* -*- C++ -*- */
// Timeprobe.h,v 4.26 1998/12/07 02:55:23 irfan Exp

// ============================================================================
//
// = LIBRARY
//    ace
//
// = FILENAME
//    Timeprobe.h
//
// = AUTHOR
//    Irfan Pyarali
//
// = ADDITIONAL COMMENTS
//
//    If users want to use time probes, the ACE_COMPILE_TIMEPROBES
//    flag must be defined when compiling ACE.  This can be achieved
//    by doing one of the following:
//
//    . Use make probe = 1, if you are using the make utility.
//
//    . Define ACE_COMPILE_TIMEPROBES in config.h
//
//    . Define ACE_COMPILE_TIMEPROBES in the VC project file.
//
//    . Other regular methods will also work.
//
//    It is not necessary to define ACE_COMPILE_TIMEPROBES when using
//    time probes, you simply need ACE_ENABLE_TIMEPROBES.  You can use
//    the ACE_TIMEPROBE_* macros to program the time probes, and use
//    the ACE_ENABLE_TIMEPROBE to enable the time probes.  If you
//    define ACE_ENABLE_TIMEPROBE in your code, but forget to compile
//    ACE with ACE_COMPILE_TIMEPROBES, you will end up with linker
//    errors.
//
//    Remember that ACE_COMPILE_TIMEPROBES means that the ACE library
//    will contain code for time probes.  This is only useful when
//    compiling ACE. ACE_ENABLE_TIMEPROBES means that the
//    ACE_TIMEPROBE_* macros should spring to life.
//
// ============================================================================

#ifndef ACE_TIMEPROBE_H
#define ACE_TIMEPROBE_H

#include "ace/OS.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#if defined (ACE_ENABLE_TIMEPROBES)
  #if !defined (ACE_COMPILE_TIMEPROBES)
    #define ACE_COMPILE_TIMEPROBES
  #endif /* ACE_COMPILE_TIMEPROBES */
#endif /* ACE_ENABLE_TIMEPROBES */

#if defined (ACE_COMPILE_TIMEPROBES)

class ACE_Export ACE_Event_Descriptions
{
  // = TITLE
  // Event Descriptions.
public:
  const char **descriptions_;
  // Event descriptions

  u_long minimum_id_;
  // Minimum id of this description set

  int operator== (const ACE_Event_Descriptions &rhs) const;
  // Comparison
};

class ACE_Export ACE_timeprobe_t
{
  // = TITLE
  //   Time probe record.
public:
  // = Events are record as strings or numbers.
  union event
  {
    u_long event_number_;
    const char *event_description_;
  };

  // = Type of event.
  enum event_type
  {
    NUMBER,
    STRING
  };

  event event_;
  // Event.

  event_type event_type_;
  // Type of event.

  ACE_hrtime_t time_;
  // Timestamp.

  ACE_thread_t thread_;
  // Id of thread posting the time probe.
};

#if defined (__ACE_INLINE__)
#include "ace/Timeprobe.i"
#endif /* __ACE_INLINE__ */

#include "ace/Timeprobe_T.h"
#include "ace/Synch.h"
#include "ace/Singleton.h"

// If ACE_MT_TIMEPROBES is defined, use a Thread_Mutex to lock the
// internal state of ACE_Timerprobe.  This allows multiple threads to
// use the same ACE_Timerprobe.
#  if defined (ACE_MT_TIMEPROBES)
typedef ACE_SYNCH_MUTEX ACE_TIMEPROBE_MUTEX;
#  else /* ACE_MT_TIMEPROBES */
typedef ACE_SYNCH_NULL_MUTEX ACE_TIMEPROBE_MUTEX;
#  endif /* ACE_MT_TIMEPROBES */

typedef ACE_Timeprobe<ACE_TIMEPROBE_MUTEX>
        ACE_TIMEPROBE_WITH_LOCKING;

// If ACE_TSS_TIMEPROBES is defined, store the ACE_Timeprobe singleton
// in thread specific storage.  This allows multiple threads to use
// their own instance of ACE_Timerprobe, without interfering with each
// other.
#  if defined (ACE_TSS_TIMEPROBES)
#define ACE_TIMEPROBE_SINGLETON_DEFINE \
        ACE_TSS_Singleton<ACE_TIMEPROBE_WITH_LOCKING, ACE_SYNCH_NULL_MUTEX>;
typedef ACE_TSS_Singleton<ACE_TIMEPROBE_WITH_LOCKING, ACE_SYNCH_NULL_MUTEX>
        ACE_TIMEPROBE_SINGLETON;
#  else /* ACE_TSS_TIMEPROBES */
#define ACE_TIMEPROBE_SINGLETON_DEFINE \
        ACE_Singleton<ACE_TIMEPROBE_WITH_LOCKING, ACE_SYNCH_MUTEX>;
typedef ACE_Singleton<ACE_TIMEPROBE_WITH_LOCKING, ACE_SYNCH_MUTEX>
        ACE_TIMEPROBE_SINGLETON;
#  endif /* ACE_TSS_TIMEPROBES */

#if defined (_MSC_VER)
// Disable warning of using Microsoft Extension.
#pragma warning(disable:4231)
#endif /* _MSC_VER */

ACE_SINGLETON_DECLARATION (ACE_TIMEPROBE_SINGLETON_DEFINE);

#if defined (_MSC_VER)
// Default back the warning of using Microsoft Extension.
#pragma warning(default:4231)
#endif /* _MSC_VER */

#endif /* ACE_COMPILE_TIMEPROBES */

// If ACE_ENABLE_TIMEPROBES is defined, the macros below will
// work. Otherwise, they just vanish.  Using this macro, you can
// control which files/libraries are probed.
#if defined (ACE_ENABLE_TIMEPROBES) && defined (ACE_COMPILE_TIMEPROBES)

#  define ACE_TIMEPROBE_RESET ACE_TIMEPROBE_SINGLETON::instance ()->reset ()
#  define ACE_TIMEPROBE(id) ACE_TIMEPROBE_SINGLETON::instance ()->timeprobe (id)
#  define ACE_TIMEPROBE_PRINT ACE_TIMEPROBE_SINGLETON::instance ()->print_times ()
#  define ACE_TIMEPROBE_PRINT_ABSOLUTE ACE_TIMEPROBE_SINGLETON::instance ()->print_absolute_times ()
#  define ACE_TIMEPROBE_EVENT_DESCRIPTIONS(descriptions, minimum_id) static int ace_timeprobe_##descriptions##_return = ACE_TIMEPROBE_SINGLETON::instance ()->event_descriptions (descriptions, minimum_id)
#  define ACE_FUNCTION_TIMEPROBE(X) ACE_Function_Timeprobe<ACE_TIMEPROBE_WITH_LOCKING> function_timeprobe (*ACE_TIMEPROBE_SINGLETON::instance (), X)

#else /* ACE_ENABLE_TIMEPROBES && ACE_COMPILE_TIMEPROBES */

#  define ACE_TIMEPROBE_RESET
#  define ACE_TIMEPROBE(id)
#  define ACE_TIMEPROBE_PRINT
#  define ACE_TIMEPROBE_PRINT_ABSOLUTE
#  define ACE_TIMEPROBE_EVENT_DESCRIPTIONS(descriptions, minimum_id)
#  define ACE_FUNCTION_TIMEPROBE(X)

#endif /* ACE_ENABLE_TIMEPROBES && ACE_COMPILE_TIMEPROBES */
#endif /* ACE_TIMEPROBE_H */
