2016-02-16 23:21:12 +03:00
|
|
|
#include "profile_manager.h"
|
|
|
|
|
2016-02-18 19:27:17 +03:00
|
|
|
#include <thread>
|
2016-02-20 19:21:14 +03:00
|
|
|
#include <string.h>
|
2016-02-24 00:08:13 +03:00
|
|
|
#include <fstream>
|
|
|
|
|
2016-02-16 23:21:12 +03:00
|
|
|
using namespace profiler;
|
|
|
|
|
|
|
|
extern "C"{
|
|
|
|
|
2016-02-17 18:18:06 +03:00
|
|
|
void PROFILER_API endBlock()
|
|
|
|
{
|
|
|
|
ProfileManager::instance().endBlock();
|
|
|
|
}
|
2016-02-18 00:45:13 +03:00
|
|
|
|
2016-02-17 18:18:06 +03:00
|
|
|
void PROFILER_API setEnabled(bool isEnable)
|
|
|
|
{
|
|
|
|
ProfileManager::instance().setEnabled(isEnable);
|
|
|
|
}
|
2016-02-18 00:45:13 +03:00
|
|
|
void PROFILER_API beginBlock(Block* _block)
|
|
|
|
{
|
2016-02-17 18:18:06 +03:00
|
|
|
ProfileManager::instance().beginBlock(_block);
|
2016-02-18 00:45:13 +03:00
|
|
|
}
|
2016-02-16 23:21:12 +03:00
|
|
|
}
|
|
|
|
|
2016-02-20 05:24:12 +03:00
|
|
|
SerilizedBlock::SerilizedBlock(Block* block):
|
|
|
|
m_size(0),
|
|
|
|
m_data(nullptr)
|
|
|
|
{
|
|
|
|
m_size += sizeof(BaseBlockData);
|
|
|
|
auto name_len = strlen(block->getName()) + 1;
|
|
|
|
m_size += name_len;
|
|
|
|
|
|
|
|
m_data = new char[m_size];
|
|
|
|
memcpy(&m_data[0], block, sizeof(BaseBlockData));
|
|
|
|
strncpy(&m_data[sizeof(BaseBlockData)], block->getName(), name_len);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
SerilizedBlock::~SerilizedBlock()
|
|
|
|
{
|
|
|
|
if (m_data){
|
|
|
|
delete[] m_data;
|
|
|
|
m_data = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-16 23:21:12 +03:00
|
|
|
|
|
|
|
ProfileManager::ProfileManager()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-02-20 05:24:12 +03:00
|
|
|
ProfileManager::~ProfileManager()
|
|
|
|
{
|
|
|
|
for (auto* b : m_blocks){
|
|
|
|
delete b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-17 18:18:06 +03:00
|
|
|
ProfileManager& ProfileManager::instance()
|
2016-02-16 23:21:12 +03:00
|
|
|
{
|
2016-02-17 18:18:06 +03:00
|
|
|
///C++11 makes possible to create Singleton without any warry about thread-safeness
|
|
|
|
///http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/
|
|
|
|
static ProfileManager m_profileManager;
|
|
|
|
return m_profileManager;
|
2016-02-16 23:21:12 +03:00
|
|
|
}
|
|
|
|
|
2016-02-18 19:27:17 +03:00
|
|
|
void ProfileManager::beginBlock(Block* _block)
|
2016-02-18 00:45:13 +03:00
|
|
|
{
|
2016-02-18 19:27:17 +03:00
|
|
|
if (!m_isEnabled)
|
|
|
|
return;
|
2016-02-20 05:24:12 +03:00
|
|
|
if (_block->getType() != BLOCK_TYPE_MARK){
|
|
|
|
guard_lock_t lock(m_spin);
|
|
|
|
m_openedBracketsMap[_block->getThreadId()].push(_block);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
_internalInsertBlock(_block);
|
|
|
|
}
|
|
|
|
|
2016-02-18 00:45:13 +03:00
|
|
|
}
|
|
|
|
|
2016-02-16 23:21:12 +03:00
|
|
|
void ProfileManager::endBlock()
|
|
|
|
{
|
2016-02-24 00:08:13 +03:00
|
|
|
|
2016-02-18 19:27:17 +03:00
|
|
|
if (!m_isEnabled)
|
|
|
|
return;
|
|
|
|
|
2016-02-24 00:08:13 +03:00
|
|
|
uint32_t threadId = std::hash<std::thread::id>()(std::this_thread::get_id());
|
2016-02-18 19:27:17 +03:00
|
|
|
|
|
|
|
guard_lock_t lock(m_spin);
|
|
|
|
auto& stackOfOpenedBlocks = m_openedBracketsMap[threadId];
|
|
|
|
|
|
|
|
if (stackOfOpenedBlocks.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Block* lastBlock = stackOfOpenedBlocks.top();
|
|
|
|
|
|
|
|
if (lastBlock && !lastBlock->isFinished()){
|
|
|
|
lastBlock->finish();
|
|
|
|
}
|
2016-02-20 05:24:12 +03:00
|
|
|
_internalInsertBlock(lastBlock);
|
2016-02-18 19:27:17 +03:00
|
|
|
stackOfOpenedBlocks.pop();
|
2016-02-16 23:21:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void ProfileManager::setEnabled(bool isEnable)
|
|
|
|
{
|
|
|
|
m_isEnabled = isEnable;
|
2016-02-16 23:25:12 +03:00
|
|
|
}
|
2016-02-20 05:24:12 +03:00
|
|
|
|
|
|
|
void ProfileManager::_internalInsertBlock(profiler::Block* _block)
|
|
|
|
{
|
|
|
|
guard_lock_t lock(m_storedSpin);
|
|
|
|
m_blocks.emplace_back(new SerilizedBlock(_block));
|
2016-02-20 19:21:14 +03:00
|
|
|
}
|
|
|
|
|