• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _TLSWRAPPER_HPP
2 #define _TLSWRAPPER_HPP
3 
4 /*
5  * Copyright (c) 2021 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * SPDX-License-Identifier: Apache-2.0
20  *
21  *//*!
22  * \file
23  * \brief Defines TLSContainer for CTS
24  */
25 
26 #include <mutex>
27 #include <thread>
28 
29 template <class T>
30 class TLSContainer {
31     struct item {
32         std::thread::id owner;
33         T * p;
34     };
35     std::mutex mutex;
36     std::vector<item> all;
37 public:
find(bool remove)38     T * find(bool remove) {
39         T * r = nullptr;
40         std::thread::id tid = std::this_thread::get_id();
41         mutex.lock();
42         for(uint32_t i=0; i < all.size(); i++) {
43             if (all[i].owner == tid) {
44                 r = all[i].p;
45                 if (remove) {
46                     all.erase(all.begin() + i);
47                 }
48                 break;
49             }
50         }
51         mutex.unlock();
52         return r;
53     }
54 
add(T * p)55     void add(T * p) {
56         item i;
57         i.owner = std::this_thread::get_id();
58         i.p = p;
59         mutex.lock();
60         all.push_back(i);
61         mutex.unlock();
62     }
TLSContainer()63     TLSContainer() {}
~TLSContainer()64     ~TLSContainer() {}
65 
66     static TLSContainer<T> instance;
67 };
68 
69 template <class T>
70 class TLSWrapper
71 {
72 public:
TLSWrapper()73     TLSWrapper() {}
~TLSWrapper()74     ~TLSWrapper() {
75         T * p = TLSContainer<T>::instance.find(true);
76         if (p) {
77             delete p;
78         }
79     }
attach()80     T & attach() {
81         T * p = TLSContainer<T>::instance.find(false);
82         if (!p ){
83             p = new T();
84             TLSContainer<T>::instance.add(p);
85         }
86         return *p;
87     }
88     static thread_local TLSWrapper<T> instance;
89 };
90 
91 #define TLS_INSTANCE()													\
92 	template<class T> TLSContainer<T> TLSContainer<T>::instance;		\
93 	template<class T> thread_local TLSWrapper<T> TLSWrapper<T>::instance
94 
95 #endif // _TLSWRAPPER_HPP
96