blob: 5fd00345ae07d403aa1ca201733d7680df760275 [file] [log] [blame]
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NB_MEMORY_SCOPE_H_
#define NB_MEMORY_SCOPE_H_
///////////////////////////////////////////////////////////////////////////////
// Macros to define the memory scope objects. These are objects that are used
// to annotate sections of the code base as belonging to a particular memory
// scope. Note that this is an annotation and does not memory allocation.
///////////////////////////////////////////////////////////////////////////////
// Macro to track the memory scope inside a function or block of code. The
// memory scope is in effect until the end of the code block.
// Example:
// void Foo() {
// TRACK_MEMORY_SCOPE("FooMemoryScope");
// // pops the memory scope at the end.
// }
#if !defined(__cplusplus)
// Disallow macro use for non-C++ builds.
#define TRACK_MEMORY_SCOPE(STR) error_forbidden_in_non_c_plus_plus_code
#define TRACK_MEMORY_SCOPE_DYNAMIC(STR) error_forbidden_in_non_c_plus_plus_code
#elif defined(STARBOARD_ALLOWS_MEMORY_TRACKING)
#define TRACK_MEMORY_SCOPE(STR) TRACK_MEMORY_STATIC_CACHED(STR)
#define TRACK_MEMORY_SCOPE_DYNAMIC(STR) TRACK_MEMORY_STATIC_NOT_CACHED(STR)
#else
// No-op when starboard does not allow memory tracking.
#define TRACK_MEMORY_SCOPE(STR)
#define TRACK_MEMORY_SCOPE_DYNAMIC(STR)
#endif
// Preprocessor needs double expansion in order to __FILE__, __LINE__ and
// __FUNCTION__ properly.
#define TRACK_MEMORY_STATIC_CACHED(STR) \
TRACK_MEMORY_STATIC_CACHED_IMPL_2(STR, __FILE__, __LINE__, __FUNCTION__)
#define TRACK_MEMORY_STATIC_NOT_CACHED(STR) \
TRACK_MEMORY_STATIC_NOT_CACHED_IMPL_2(STR, __FILE__, __LINE__, __FUNCTION__)
// Only enable TRACK_MEMORY_STATIC_CACHED_IMPL_2 if starboard allows memory
// tracking.
#define TRACK_MEMORY_STATIC_CACHED_IMPL_2(Str, FileStr, LineNum, FuncStr) \
static NbMemoryScopeInfo memory_scope_handle_##LineNum = \
{ NULL, Str, FileStr, LineNum, FuncStr, true }; \
NbPushMemoryScope(&memory_scope_handle_##LineNum); \
NbPopMemoryScopeOnScopeEnd pop_on_scope_end_##LineNum; \
(void)pop_on_scope_end_##LineNum;
#define TRACK_MEMORY_STATIC_NOT_CACHED_IMPL_2(Str, FileStr, LineNum, FuncStr) \
NbMemoryScopeInfo memory_scope_handle_##LineNum = { \
NULL, Str, FileStr, LineNum, FuncStr, false}; \
NbPushMemoryScope(&memory_scope_handle_##LineNum); \
NbPopMemoryScopeOnScopeEnd pop_on_scope_end_##LineNum; \
(void)pop_on_scope_end_##LineNum;
#ifdef __cplusplus
extern "C" {
#endif
struct NbMemoryScopeReporter;
struct NbMemoryScopeInfo;
// Sets the memory reporter. Returns true on success, false something
// goes wrong.
bool NbSetMemoryScopeReporter(NbMemoryScopeReporter* reporter);
// Note that we pass by pointer because the memory scope contains a
// variable allowing the result to be cached.
void NbPushMemoryScope(NbMemoryScopeInfo* memory_scope);
void NbPopMemoryScope();
///////////////////////////////////////////////////////////////////////////////
// Implementation
///////////////////////////////////////////////////////////////////////////////
// Interface for handling memory scopes.
typedef void (*NbReportPushMemoryScopeCallback)(void* context,
NbMemoryScopeInfo* info);
typedef void (*NbReportPopMemoryScopeCallback)(void* context);
struct NbMemoryScopeReporter {
// Callback to report pushing of memory scope.
NbReportPushMemoryScopeCallback push_memory_scope_cb;
// Callback to report poping of the memory scope.
NbReportPopMemoryScopeCallback pop_memory_scope_cb;
// Optional, is passed to the callbacks as first argument.
void* context;
};
// This MemoryScope must remain a POD data type so that it can be statically
// initialized.
struct NbMemoryScopeInfo {
// cached_handle_ allows a cached result of the the fields represented in
// this struct to be generated and the handle be placed into this field.
// See also allows_caching_.
void* cached_handle_;
// Represents the name of the memory scope. I.E. "Javascript" or "Gfx".
const char* memory_scope_name_;
// Represents the file name that this memory scope was created at.
const char* file_name_;
// Represents the line number that this memory scope was created at.
int line_number_;
// Represents the function name that this memory scope was created at.
const char* function_name_;
// When true, if cached_handle_ is 0 then an object may be created that
// represents the fields of this object. The handle that represents this
// cached object is then placed in cached_hanlde_.
bool allows_caching_;
};
// NbPopMemoryScopeOnScopeEnd is only allowed for C++ builds.
#ifdef __cplusplus
// A helper that pops the memory scope at the end of the current code block.
struct NbPopMemoryScopeOnScopeEnd {
~NbPopMemoryScopeOnScopeEnd() { NbPopMemoryScope(); }
};
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif // NB_MEMORY_SCOPE_H_