@@ -64,101 +64,6 @@ template <> uint32_t inline pi_cast(uint64_t Value) {
64
64
return CastedValue;
65
65
}
66
66
67
- // The wrapper for immutable Level-Zero data.
68
- // The data is initialized only once at first access (via ->) with the
69
- // initialization function provided in Init. All subsequent access to
70
- // the data just returns the already stored data.
71
- //
72
- template <class T > struct ZeCache : private T {
73
- // The initialization function takes a reference to the data
74
- // it is going to initialize, since it is private here in
75
- // order to disallow access other than through "->".
76
- //
77
- using InitFunctionType = std::function<void (T &)>;
78
- InitFunctionType Compute{nullptr };
79
- bool Computed{false };
80
- pi_mutex ZeCacheMutex;
81
-
82
- ZeCache () : T{} {}
83
-
84
- // Access to the fields of the original T data structure.
85
- T *operator ->() {
86
- std::unique_lock<pi_mutex> Lock (ZeCacheMutex);
87
- if (!Computed) {
88
- Compute (*this );
89
- Computed = true ;
90
- }
91
- return this ;
92
- }
93
- };
94
-
95
- // This wrapper around std::atomic is created to limit operations with reference
96
- // counter and to make allowed operations more transparent in terms of
97
- // thread-safety in the plugin. increment() and load() operations do not need a
98
- // mutex guard around them since the underlying data is already atomic.
99
- // decrementAndTest() method is used to guard a code which needs to be
100
- // executed when object's ref count becomes zero after release. This method also
101
- // doesn't need a mutex guard because decrement operation is atomic and only one
102
- // thread can reach ref count equal to zero, i.e. only a single thread can pass
103
- // through this check.
104
- struct ReferenceCounter {
105
- ReferenceCounter () : RefCount{1 } {}
106
-
107
- // Reset the counter to the initial value.
108
- void reset () { RefCount = 1 ; }
109
-
110
- // Used when retaining an object.
111
- void increment () { RefCount++; }
112
-
113
- // Supposed to be used in pi*GetInfo* methods where ref count value is
114
- // requested.
115
- pi_uint32 load () { return RefCount.load (); }
116
-
117
- // This method allows to guard a code which needs to be executed when object's
118
- // ref count becomes zero after release. It is important to notice that only a
119
- // single thread can pass through this check. This is true because of several
120
- // reasons:
121
- // 1. Decrement operation is executed atomically.
122
- // 2. It is not allowed to retain an object after its refcount reaches zero.
123
- // 3. It is not allowed to release an object more times than the value of
124
- // the ref count.
125
- // 2. and 3. basically means that we can't use an object at all as soon as its
126
- // refcount reaches zero. Using this check guarantees that code for deleting
127
- // an object and releasing its resources is executed once by a single thread
128
- // and we don't need to use any mutexes to guard access to this object in the
129
- // scope after this check. Of course if we access another objects in this code
130
- // (not the one which is being deleted) then access to these objects must be
131
- // guarded, for example with a mutex.
132
- bool decrementAndTest () { return --RefCount == 0 ; }
133
-
134
- private:
135
- std::atomic<pi_uint32> RefCount;
136
- };
137
-
138
- // Base class to store common data
139
- struct _pi_object {
140
- _pi_object () : RefCount{} {}
141
-
142
- // Level Zero doesn't do the reference counting, so we have to do.
143
- // Must be atomic to prevent data race when incrementing/decrementing.
144
- ReferenceCounter RefCount;
145
-
146
- // This mutex protects accesses to all the non-const member variables.
147
- // Exclusive access is required to modify any of these members.
148
- //
149
- // To get shared access to the object in a scope use std::shared_lock:
150
- // std::shared_lock Lock(Obj->Mutex);
151
- // To get exclusive access to the object in a scope use std::scoped_lock:
152
- // std::scoped_lock Lock(Obj->Mutex);
153
- //
154
- // If several pi objects are accessed in a scope then each object's mutex must
155
- // be locked. For example, to get write access to Obj1 and Obj2 and read
156
- // access to Obj3 in a scope use the following approach:
157
- // std::shared_lock Obj3Lock(Obj3->Mutex, std::defer_lock);
158
- // std::scoped_lock LockAll(Obj1->Mutex, Obj2->Mutex, Obj3Lock);
159
- pi_shared_mutex Mutex;
160
- };
161
-
162
67
// Record for a memory allocation. This structure is used to keep information
163
68
// for each memory allocation.
164
69
struct MemAllocRecord : _pi_object {
0 commit comments