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