156 lines
4.9 KiB
C++
156 lines
4.9 KiB
C++
/*
|
|
DIAGNOSTIC-CONTEXT.hpp - thread local stack for explicitly collecting diagnostic context info
|
|
|
|
Copyright (C) Lumiera.org
|
|
2010, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
/** @file diagnostic-context.hpp
|
|
** Facility for collecting diagnostic informations explicitly.
|
|
** Unlike a trace logging run, this facility is intended to be fed explicitly with
|
|
** diagnostic information describing the currently ongoing operation in a semantic
|
|
** high-level manner. The rationale is to pinpoint \em those informations which aren't
|
|
** obvious when just looking at a callstack with the debugger. Instances of the class
|
|
** DiagnosticContext should be placed explicitly as automatic (stack) variable
|
|
** into selected relevant scopes; these "information frames" can be accessed
|
|
** from an enclosed scope as a per-thread stack. DiagnosticContext provides
|
|
** an controlled environment for adding diagnostic code on demand; typically
|
|
** to be configured such as to resolve into an empty class for release builds.
|
|
**
|
|
** As of 2/10, this is an experimental feature in evaluation. To start with,
|
|
** I'll use it to solve the problem of providing a NoBug resource tracker handle
|
|
** without tangling the object monitor code (sync.hpp) with low level, NoBug related
|
|
** implementation details.
|
|
**
|
|
** @todo add the actual diagnostic content
|
|
**/
|
|
|
|
|
|
#ifndef LIB_DIAGNOSTIC_CONTEXT_H
|
|
#define LIB_DIAGNOSTIC_CONTEXT_H
|
|
|
|
|
|
#include "lib/error.hpp"
|
|
#include "lib/thread-local.hpp"
|
|
|
|
#include <boost/noncopyable.hpp>
|
|
#include <nobug.h>
|
|
|
|
|
|
|
|
namespace lib {
|
|
|
|
|
|
|
|
#ifdef NOBUG_MODE_ALPHA ////////////////////////TODO don't we need the handle in BETA builds for resource logging?
|
|
|
|
/**
|
|
* Diagnostic data frame to collect specific informations concerning a scope.
|
|
* To be placed explicitly as an automatic (stack) variable. Provides a controlled
|
|
* environment for hooking up diagnostic code. Within each thread, a stack of
|
|
* such information frames concerning nested scopes is maintained automatically.
|
|
* It can be accessed via static API.
|
|
* @warning never store this into global data structures.
|
|
* @note as of 2/10 used for housing the NoBug resource tracker handle
|
|
* in conjunction with object monitor based locking
|
|
* @see sync.hpp
|
|
*/
|
|
class DiagnosticContext
|
|
: boost::noncopyable
|
|
{
|
|
typedef nobug_resource_user* Handle;
|
|
typedef ThreadLocalPtr<DiagnosticContext> ThreadLocalAccess;
|
|
|
|
Handle handle_;
|
|
DiagnosticContext * const prev_;
|
|
|
|
/** embedded thread local pointer
|
|
* to the innermost context encountered */
|
|
static ThreadLocalAccess&
|
|
current()
|
|
{
|
|
static ThreadLocalAccess accessPoint;
|
|
return accessPoint;
|
|
}
|
|
|
|
|
|
public:
|
|
DiagnosticContext()
|
|
: handle_(0)
|
|
, prev_(current().get())
|
|
{
|
|
current().set (this);
|
|
}
|
|
|
|
~DiagnosticContext()
|
|
{
|
|
ASSERT (this == current().get());
|
|
current().set (prev_);
|
|
}
|
|
|
|
|
|
operator Handle* () ///< payload: NoBug resource tracker user handle
|
|
{
|
|
return &handle_;
|
|
}
|
|
|
|
/** accessing the innermost diagnostic context created */
|
|
static DiagnosticContext&
|
|
access ()
|
|
{
|
|
DiagnosticContext* innermost = current().get();
|
|
if (!innermost)
|
|
throw lumiera::error::Logic ("Accessing Diagnostic context out of order; "
|
|
"an instance should have been created in "
|
|
"an enclosing scope");
|
|
return *innermost;
|
|
}
|
|
};
|
|
|
|
|
|
#else /* not NOBUG_ALPHA */
|
|
|
|
|
|
/**
|
|
* Disabled placeholder for the Diagnostic context, not used in release builds.
|
|
*/
|
|
class DiagnosticContext
|
|
: boost::noncopyable
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
operator Handle* () ///< payload: NoBug resource tracker user handle
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/** accessing the innermost diagnostic context created */
|
|
static DiagnosticContext&
|
|
access ()
|
|
{
|
|
UNIMPLEMENTED ("how to disable DiagnosticContext with minimum overhead");
|
|
}
|
|
};
|
|
#endif /* NOBUG_ALPHA? */
|
|
|
|
|
|
|
|
} // namespace lib
|
|
#endif
|