1 /** 2 Lightweight profiler library for c++ 3 Copyright(C) 2016-2017 Sergey Yagovtsev, Victor Zarubkin 4 5 Licensed under either of 6 * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) 7 * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0) 8 at your option. 9 10 The MIT License 11 Permission is hereby granted, free of charge, to any person obtaining a copy 12 of this software and associated documentation files (the "Software"), to deal 13 in the Software without restriction, including without limitation the rights 14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 15 of the Software, and to permit persons to whom the Software is furnished 16 to do so, subject to the following conditions: 17 18 The above copyright notice and this permission notice shall be included in all 19 copies or substantial portions of the Software. 20 21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 22 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 23 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 26 USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28 29 The Apache License, Version 2.0 (the "License"); 30 You may not use this file except in compliance with the License. 31 You may obtain a copy of the License at 32 33 http://www.apache.org/licenses/LICENSE-2.0 34 35 Unless required by applicable law or agreed to in writing, software 36 distributed under the License is distributed on an "AS IS" BASIS, 37 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 38 See the License for the specific language governing permissions and 39 limitations under the License. 40 41 **/ 42 43 #ifndef EASY_PROFILER_THREAD_STORAGE_H 44 #define EASY_PROFILER_THREAD_STORAGE_H 45 46 #include <easy/details/profiler_public_types.h> 47 #include <easy/details/arbitrary_value_public_types.h> 48 #include <easy/serialized_block.h> 49 #include <vector> 50 #include <string> 51 #include <atomic> 52 #include <functional> 53 #include "stack_buffer.h" 54 #include "chunk_allocator.h" 55 56 ////////////////////////////////////////////////////////////////////////// 57 58 template <class T, const uint16_t N> 59 struct BlocksList 60 { 61 BlocksList() = default; 62 63 std::vector<T> openedList; 64 chunk_allocator<N> closedList; 65 uint64_t usedMemorySize = 0; 66 clearClosedBlocksList67 void clearClosed() { 68 //closedList.clear(); 69 usedMemorySize = 0; 70 } 71 72 private: 73 74 BlocksList(const BlocksList&) = delete; 75 BlocksList(BlocksList&&) = delete; 76 77 }; // END of struct BlocksList. 78 79 ////////////////////////////////////////////////////////////////////////// 80 81 class CSwitchBlock : public profiler::CSwitchEvent 82 { 83 const char* m_name; 84 85 public: 86 87 CSwitchBlock(profiler::timestamp_t _begin_time, profiler::thread_id_t _tid, const char* _runtimeName) EASY_NOEXCEPT; name()88 inline const char* name() const EASY_NOEXCEPT { return m_name; } 89 }; 90 91 ////////////////////////////////////////////////////////////////////////// 92 93 const uint16_t SIZEOF_BLOCK = sizeof(profiler::BaseBlockData) + 1 + sizeof(uint16_t); // SerializedBlock stores BaseBlockData + at least 1 character for name ('\0') + 2 bytes for size of serialized data 94 const uint16_t SIZEOF_CSWITCH = sizeof(profiler::CSwitchEvent) + 1 + sizeof(uint16_t); // SerializedCSwitch also stores additional 4 bytes to be able to save 64-bit thread_id 95 96 struct ThreadStorage EASY_FINAL 97 { 98 StackBuffer<NonscopedBlock> nonscopedBlocks; 99 BlocksList<std::reference_wrapper<profiler::Block>, SIZEOF_BLOCK * (uint16_t)128U> blocks; 100 BlocksList<CSwitchBlock, SIZEOF_CSWITCH * (uint16_t)128U> sync; 101 102 std::string name; ///< Thread name 103 profiler::timestamp_t frameStartTime; ///< Current frame start time. Used to calculate FPS. 104 const profiler::thread_id_t id; ///< Thread ID 105 std::atomic<char> expired; ///< Is thread expired 106 std::atomic_bool profiledFrameOpened; ///< Is new profiled frame opened (this is true when profiling is enabled and there is an opened frame) \sa frameOpened 107 int32_t stackSize; ///< Current thread stack depth. Used when switching profiler state to begin collecting blocks only when new frame would be opened. 108 bool allowChildren; ///< False if one of previously opened blocks has OFF_RECURSIVE or ON_WITHOUT_CHILDREN status 109 bool named; ///< True if thread name was set 110 bool guarded; ///< True if thread has been registered using ThreadGuard 111 bool frameOpened; ///< Is new frame opened (this does not depend on profiling status) \sa profiledFrameOpened 112 bool halt; ///< This is set to true when new frame started while dumping blocks. Used to restrict collecting blocks during dumping process. 113 114 void storeValue(profiler::timestamp_t _timestamp, profiler::block_id_t _id, profiler::DataType _type, const void* _data, size_t _size, bool _isArray, profiler::ValueId _vin); 115 void storeBlock(const profiler::Block& _block); 116 void storeCSwitch(const CSwitchBlock& _block); 117 void clearClosed(); 118 void popSilent(); 119 120 void beginFrame(); 121 profiler::timestamp_t endFrame(); 122 123 ThreadStorage(); 124 125 private: 126 127 ThreadStorage(const ThreadStorage&) = delete; 128 ThreadStorage(ThreadStorage&&) = delete; 129 130 }; // END of struct ThreadStorage. 131 132 ////////////////////////////////////////////////////////////////////////// 133 134 #endif // EASY_PROFILER_THREAD_STORAGE_H 135