Line data Source code
1 : /** 2 : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org> 3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev> 4 : 5 : Permission is hereby granted, free of charge, to any person obtaining a copy 6 : of this software and associated documentation files (the "Software"), to deal 7 : in the Software without restriction, including without limitation the rights 8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 : copies of the Software, and to permit persons to whom the Software is 10 : furnished to do so, subject to the following conditions: 11 : 12 : The above copyright notice and this permission notice shall be included in 13 : all copies or substantial portions of the Software. 14 : 15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 : THE SOFTWARE. 22 : **/ 23 : 24 : #include "SPCommon.h" 25 : #include "SPThread.h" 26 : 27 : namespace STAPPLER_VERSIONIZED stappler::thread { 28 : 29 : struct ThreadCallbacks { 30 : void (*init) (void *); 31 : void (*dispose) (void *); 32 : bool (*worker) (void *); 33 : }; 34 : 35 : void _workerThread(const ThreadCallbacks &tm, void *); 36 : 37 : static std::atomic<uint32_t> s_threadId(1); 38 : 39 0 : SPUNUSED static uint32_t getNextThreadId() { 40 0 : auto id = s_threadId.fetch_add(1); 41 0 : return (id % 0xFFFF) + (1 << 16); 42 : } 43 : 44 : thread_local const void *tl_owner = nullptr; 45 : 46 : template <> 47 0 : const void *ThreadInterface<memory::StandartInterface>::getOwner() { 48 0 : return tl_owner; 49 : } 50 : 51 : template <> 52 0 : const void *ThreadInterface<memory::PoolInterface>::getOwner() { 53 0 : return tl_owner; 54 : } 55 : 56 : template <> 57 425 : void ThreadInterface<memory::StandartInterface>::workerThread(ThreadInterface<memory::StandartInterface> *tm, const void *q) { 58 425 : tl_owner = q; 59 : 60 : ThreadCallbacks cb; 61 850 : cb.init = [] (void *obj) { 62 425 : ((ThreadInterface<memory::StandartInterface> *)obj)->threadInit(); 63 425 : }; 64 : 65 795 : cb.dispose = [] (void *obj) { 66 370 : ((ThreadInterface<memory::StandartInterface> *)obj)->threadDispose(); 67 425 : }; 68 : 69 215841625 : cb.worker = [] (void *obj) -> bool { 70 215841200 : return ((ThreadInterface<memory::StandartInterface> *)obj)->worker(); 71 425 : }; 72 : 73 425 : memory::pool::initialize(); 74 425 : _workerThread(cb, tm); 75 368 : memory::pool::terminate(); 76 364 : } 77 : 78 : template <> 79 200 : void ThreadInterface<memory::PoolInterface>::workerThread(ThreadInterface<memory::PoolInterface> *tm, const void *q) { 80 200 : tl_owner = q; 81 : 82 : ThreadCallbacks cb; 83 399 : cb.init = [] (void *obj) { 84 199 : ((ThreadInterface<memory::PoolInterface> *)obj)->threadInit(); 85 200 : }; 86 : 87 389 : cb.dispose = [] (void *obj) { 88 189 : ((ThreadInterface<memory::PoolInterface> *)obj)->threadDispose(); 89 200 : }; 90 : 91 590 : cb.worker = [] (void *obj) -> bool { 92 390 : return ((ThreadInterface<memory::PoolInterface> *)obj)->worker(); 93 200 : }; 94 : 95 200 : memory::pool::initialize(); 96 199 : _workerThread(cb, tm); 97 185 : memory::pool::terminate(); 98 198 : } 99 : 100 : } 101 : 102 : #include "SPThreads-android.cc" 103 : #include "SPThreads-linux.cc" 104 : #include "SPThreads-win32.cc" 105 : #include "SPThreadTask.cc" 106 : #include "SPThreadTaskQueue.cc" 107 : 108 : namespace STAPPLER_VERSIONIZED stappler::thread { 109 : 110 : thread_local ThreadInfo tl_threadInfo; 111 : 112 3864 : ThreadInfo *ThreadInfo::getThreadLocal() { 113 3864 : if (!tl_threadInfo.managed) { 114 3464 : return nullptr; 115 : } 116 : 117 400 : return &tl_threadInfo; 118 : } 119 : 120 0 : void ThreadInfo::setMainThread() { 121 0 : tl_threadInfo.threadId = mainThreadId; 122 0 : tl_threadInfo.workerId = 0; 123 0 : tl_threadInfo.name = StringView("Main"); 124 0 : tl_threadInfo.managed = true; 125 0 : } 126 : 127 250 : void ThreadInfo::setThreadInfo(uint32_t t, uint32_t w, StringView name, bool m) { 128 : #if LINUX 129 250 : pthread_setname_np(pthread_self(), name.data()); 130 : #endif 131 250 : tl_threadInfo.threadId = t; 132 250 : tl_threadInfo.workerId = w; 133 250 : tl_threadInfo.name = name; 134 250 : tl_threadInfo.managed = m; 135 250 : } 136 : 137 199 : void ThreadInfo::setThreadInfo(StringView name) { 138 : #if LINUX 139 199 : pthread_setname_np(pthread_self(), name.data()); 140 : #endif 141 200 : tl_threadInfo.threadId = 0; 142 200 : tl_threadInfo.workerId = 0; 143 200 : tl_threadInfo.name = name; 144 199 : tl_threadInfo.managed = true; 145 199 : tl_threadInfo.detouched = true; 146 199 : } 147 : 148 0 : const TaskQueue *TaskQueue::getOwner() { 149 0 : return (const TaskQueue *)tl_owner; 150 : } 151 : 152 624 : static void ThreadCallbacks_init(const ThreadCallbacks &cb, void *tm) { 153 624 : cb.init(tm); 154 624 : } 155 : 156 215835252 : static bool ThreadCallbacks_worker(const ThreadCallbacks &cb, void *tm) { 157 215835252 : return cb.worker(tm); 158 : } 159 : 160 564 : static void ThreadCallbacks_dispose(const ThreadCallbacks &cb, void *tm) { 161 564 : cb.dispose(tm); 162 555 : } 163 : 164 : }