LCOV - code coverage report
Current view: top level - muse/framework/global - allocator.h Coverage Total Hit
Test: filtered_coverage.info Lines: 80.0 % 10 8
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #ifndef MUSE_GLOBAL_ALLOCATOR_H
      23              : #define MUSE_GLOBAL_ALLOCATOR_H
      24              : 
      25              : #include <cstdint>
      26              : #include <vector>
      27              : #include <list>
      28              : #include <string>
      29              : 
      30              : namespace muse {
      31              : #define OBJECT_ALLOCATOR(Module, ClassName) \
      32              : public: \
      33              :     static muse::ObjectAllocator& allocator() { \
      34              :         static muse::ObjectAllocator a(#Module, #ClassName, muse::ObjectAllocator::destroyer<ClassName>); \
      35              :         return a; \
      36              :     } \
      37              :     static void* operator new(size_t sz) { \
      38              :         return muse::ObjectAllocator::enabled() ? allocator().alloc(sz) : ::operator new(sz); \
      39              :     } \
      40              :     static void operator delete(void* ptr) { \
      41              :         if (muse::ObjectAllocator::enabled()) { \
      42              :             allocator().free(ptr); \
      43              :         } else { \
      44              :             ::operator delete(ptr); \
      45              :         } \
      46              :     } \
      47              :     static void* operator new[](size_t sz) { \
      48              :         return muse::ObjectAllocator::enabled() ? allocator().not_supported("new[]") : ::operator new[](sz); \
      49              :     } \
      50              :     static void* operator new(size_t sz, void* ptr) { \
      51              :         return muse::ObjectAllocator::enabled() ? allocator().not_supported("new(size_t, void*)") : ::operator new(sz, ptr); \
      52              :     } \
      53              :     static void operator delete[](void* ptr) { \
      54              :         if (muse::ObjectAllocator::enabled()) { \
      55              :             allocator().not_supported("delete[]"); \
      56              :         } else { \
      57              :             ::operator delete[](ptr); \
      58              :         } \
      59              :     } \
      60              : private:
      61              : 
      62              : class ObjectAllocator
      63              : {
      64              : public:
      65              : 
      66              :     using destroyer_t = void (*)(void*);
      67              : 
      68              :     ObjectAllocator(const char* module, const char* name, destroyer_t dtor);
      69              :     ~ObjectAllocator();
      70              : 
      71              :     static size_t DEFAULT_BLOCK_SIZE;
      72              : 
      73              :     const char* module() const;
      74              :     const char* name() const;
      75              : 
      76              :     void* alloc(size_t size);
      77              :     void free(void* ptr);
      78              :     void cleanup();
      79              : 
      80              :     template<class T>
      81           11 :     static void destroyer(void* ptr)
      82              :     {
      83           11 :         T* p = reinterpret_cast<T*>(ptr);
      84           11 :         p->~T();
      85           11 :     }
      86              : 
      87              :     void* not_supported(const char* info);
      88              : 
      89              :     struct Info
      90              :     {
      91              :         std::string module;
      92              :         std::string name;
      93              :         size_t chunkSize = 0;
      94              :         size_t blockCount = 0;
      95              :         size_t totalChunks = 0;
      96              :         size_t freeChunks = 0;
      97              : 
      98              :         uint64_t totalAllocatedCount = 0;
      99              :         uint64_t totalFreeCount = 0;
     100              : 
     101            0 :         uint64_t usedChunks() const { return totalChunks - freeChunks; }
     102            0 :         uint64_t allocatedBytes() const { return totalChunks * chunkSize; }
     103              :     };
     104              : 
     105              :     Info stateInfo() const;
     106              : 
     107      1268972 :     static bool enabled() { return s_used; }
     108              :     static void used();
     109              :     static void unused();
     110              : 
     111              :     static int s_used;
     112              : private:
     113              : 
     114              :     struct Chunk {
     115              :         /**
     116              :          * When a chunk is free, the `next` contains the
     117              :          * address of the next chunk in a list.
     118              :          *
     119              :          * When it's allocated, this space is used by
     120              :          * the user.
     121              :          */
     122              :         Chunk* next = nullptr;
     123              :     };
     124              : 
     125              :     struct Block {
     126              :         Chunk* begin = nullptr;
     127              :         size_t chunkCount = 0;
     128              :         size_t chunkSize = 0;
     129              :     };
     130              : 
     131              :     Block allocateBlock(size_t chunkSize) const;
     132              : 
     133              :     const char* m_module = nullptr;
     134              :     const char* m_name = nullptr;
     135              :     size_t m_chunkSize = 0;
     136              :     destroyer_t m_dtor = nullptr;
     137              :     Chunk* m_free = nullptr;
     138              :     std::vector<Block> m_blocks;
     139              : 
     140              :     struct Statistic
     141              :     {
     142              :         uint64_t totalAllocatedCount = 0;
     143              :         uint64_t totalFreeCount = 0;
     144              :     };
     145              : 
     146              :     Statistic m_statistic;
     147              : };
     148              : 
     149              : class AllocatorsRegister
     150              : {
     151              : public:
     152              : 
     153            6 :     static AllocatorsRegister* instance()
     154              :     {
     155          211 :         static AllocatorsRegister r;
     156            6 :         return &r;
     157              :     }
     158              : 
     159              :     void reg(ObjectAllocator* a);
     160              :     void unreg(ObjectAllocator* a);
     161              : 
     162              :     void cleanupAll(const std::string& module);
     163              : 
     164              :     void printStatistic(const std::string& title);
     165              :     void printState(const std::string& title);
     166              : 
     167              : private:
     168              :     std::list<ObjectAllocator*> m_allocators;
     169              : };
     170              : }
     171              : 
     172              : #endif // MUSE_GLOBAL_ALLOCATOR_H
        

Generated by: LCOV version 2.0-1