#ifndef THIRD_PARTY_UPB_WASM_ABI_TRACE_SCOPED_TRACE_H_
#define THIRD_PARTY_UPB_WASM_ABI_TRACE_SCOPED_TRACE_H_

#if defined(__ANDROID__) && defined(XPLAT_TRACING_ENABLED)
#include <android/trace.h>

#include "third_party/absl/base/attributes.h"
#endif

// Support for Android systrace of native code. Use '--define tracing=enabled'
// to enable tracing.
//
// APIs defined in this file assume that ATrace symbols are already loaded
// properly at runtime.
// See
// https://developer.android.com/topic/performance/tracing/custom-events-native.
//
// Use:
//  XPLAT_SCOPED_TRACE("tag-name");

namespace upb::wasm::trace {

#if defined(__ANDROID__) && defined(XPLAT_TRACING_ENABLED)

class ScopedTrace {
 public:
  ABSL_ATTRIBUTE_ALWAYS_INLINE explicit inline ScopedTrace(const char* name) {
    if (__builtin_available(android 23, *)) {
      ATrace_beginSection(name);
    }
  }

  ABSL_ATTRIBUTE_ALWAYS_INLINE inline ~ScopedTrace() {
    if (__builtin_available(android 23, *)) {
      ATrace_endSection();
    }
  }

  ScopedTrace(const ScopedTrace&) = delete;
  ScopedTrace& operator=(const ScopedTrace&) = delete;
};

// Due to C++ preprocessor weirdness, we need double indirection to
// concatenate two tokens when one of them is __LINE__.  Writing
//
//   foo ## __LINE__
//
// will result in the token foo__LINE__, instead of foo followed by
// the current line number.  For more details, see
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
#define XPLAT_CONCAT_VARNAME_(prefix, n) XPLAT_CONCAT_VARNAME_IMPL_(prefix, n)
#define XPLAT_CONCAT_VARNAME_IMPL_(prefix, n) prefix##n

#define XPLAT_SCOPED_TRACE(name)                                  \
  ::upb::wasm::trace::ScopedTrace XPLAT_CONCAT_VARNAME_(__tracer, \
                                                        __LINE__)(name)

#define XPLAT_START_TRACE(name)             \
  if (__builtin_available(android 23, *)) { \
    ATrace_beginSection(name)               \
  }

#define XPLAT_END_TRACE()                   \
  if (__builtin_available(android 23, *)) { \
    ATrace_endSection()                     \
  }

#else

#define XPLAT_SCOPED_TRACE(name)

#define XPLAT_START_TRACE(name)

#define XPLAT_END_TRACE()

#endif

}  // namespace upb::wasm::trace

#endif  // THIRD_PARTY_UPB_WASM_ABI_TRACE_SCOPED_TRACE_H_
