VR-Vantage 3.0 API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TracyLock.hpp
Go to the documentation of this file.
1 #ifndef __TRACYLOCK_HPP__
2 #define __TRACYLOCK_HPP__
3 
4 #include <atomic>
5 #include <limits>
6 
7 #include "../common/TracySystem.hpp"
8 #include "../common/TracyAlign.hpp"
9 #include "TracyProfiler.hpp"
10 
11 namespace tracy
12 {
13 
15 {
16 public:
18  : m_id( GetLockCounter().fetch_add( 1, std::memory_order_relaxed ) )
19 #ifdef TRACY_ON_DEMAND
20  , m_lockCount( 0 )
21  , m_active( false )
22 #endif
23  {
25 
26  auto item = Profiler::QueueSerial();
27  MemWrite( &item->hdr.type, QueueType::LockAnnounce );
28  MemWrite( &item->lockAnnounce.id, m_id );
29  MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
30  MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
31  MemWrite( &item->lockAnnounce.type, LockType::Lockable );
32 #ifdef TRACY_ON_DEMAND
33  GetProfiler().DeferItem( *item );
34 #endif
36  }
37 
38  LockableCtx( const LockableCtx& ) = delete;
39  LockableCtx& operator=( const LockableCtx& ) = delete;
40 
42  {
43  auto item = Profiler::QueueSerial();
44  MemWrite( &item->hdr.type, QueueType::LockTerminate );
45  MemWrite( &item->lockTerminate.id, m_id );
46  MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
47 #ifdef TRACY_ON_DEMAND
48  GetProfiler().DeferItem( *item );
49 #endif
51  }
52 
54  {
55 #ifdef TRACY_ON_DEMAND
56  bool queue = false;
57  const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
58  const auto active = m_active.load( std::memory_order_relaxed );
59  if( locks == 0 || active )
60  {
61  const bool connected = GetProfiler().IsConnected();
62  if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
63  if( connected ) queue = true;
64  }
65  if( !queue ) return false;
66 #endif
67 
68  auto item = Profiler::QueueSerial();
69  MemWrite( &item->hdr.type, QueueType::LockWait );
70  MemWrite( &item->lockWait.thread, GetThreadHandle() );
71  MemWrite( &item->lockWait.id, m_id );
72  MemWrite( &item->lockWait.time, Profiler::GetTime() );
74  return true;
75  }
76 
78  {
79  auto item = Profiler::QueueSerial();
80  MemWrite( &item->hdr.type, QueueType::LockObtain );
81  MemWrite( &item->lockObtain.thread, GetThreadHandle() );
82  MemWrite( &item->lockObtain.id, m_id );
83  MemWrite( &item->lockObtain.time, Profiler::GetTime() );
85  }
86 
88  {
89 #ifdef TRACY_ON_DEMAND
90  m_lockCount.fetch_sub( 1, std::memory_order_relaxed );
91  if( !m_active.load( std::memory_order_relaxed ) ) return;
92  if( !GetProfiler().IsConnected() )
93  {
94  m_active.store( false, std::memory_order_relaxed );
95  return;
96  }
97 #endif
98 
99  auto item = Profiler::QueueSerial();
100  MemWrite( &item->hdr.type, QueueType::LockRelease );
101  MemWrite( &item->lockRelease.thread, GetThreadHandle() );
102  MemWrite( &item->lockRelease.id, m_id );
103  MemWrite( &item->lockRelease.time, Profiler::GetTime() );
105  }
106 
107  tracy_force_inline void AfterTryLock( bool acquired )
108  {
109 #ifdef TRACY_ON_DEMAND
110  if( !acquired ) return;
111 
112  bool queue = false;
113  const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
114  const auto active = m_active.load( std::memory_order_relaxed );
115  if( locks == 0 || active )
116  {
117  const bool connected = GetProfiler().IsConnected();
118  if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
119  if( connected ) queue = true;
120  }
121  if( !queue ) return;
122 #endif
123 
124  if( acquired )
125  {
126  auto item = Profiler::QueueSerial();
127  MemWrite( &item->hdr.type, QueueType::LockObtain );
128  MemWrite( &item->lockObtain.thread, GetThreadHandle() );
129  MemWrite( &item->lockObtain.id, m_id );
130  MemWrite( &item->lockObtain.time, Profiler::GetTime() );
132  }
133  }
134 
136  {
137 #ifdef TRACY_ON_DEMAND
138  const auto active = m_active.load( std::memory_order_relaxed );
139  if( !active ) return;
140  const auto connected = GetProfiler().IsConnected();
141  if( !connected )
142  {
143  if( active ) m_active.store( false, std::memory_order_relaxed );
144  return;
145  }
146 #endif
147 
148  auto item = Profiler::QueueSerial();
149  MemWrite( &item->hdr.type, QueueType::LockMark );
150  MemWrite( &item->lockMark.thread, GetThreadHandle() );
151  MemWrite( &item->lockMark.id, m_id );
152  MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc );
154  }
155 
156  tracy_force_inline void CustomName( const char* name, size_t size )
157  {
158  assert( size < std::numeric_limits<uint16_t>::max() );
159  auto ptr = (char*)tracy_malloc( size );
160  memcpy( ptr, name, size );
161  auto item = Profiler::QueueSerial();
162  MemWrite( &item->hdr.type, QueueType::LockName );
163  MemWrite( &item->lockNameFat.id, m_id );
164  MemWrite( &item->lockNameFat.name, (uint64_t)ptr );
165  MemWrite( &item->lockNameFat.size, (uint16_t)size );
166 #ifdef TRACY_ON_DEMAND
167  GetProfiler().DeferItem( *item );
168 #endif
170  }
171 
172 private:
174 
175 #ifdef TRACY_ON_DEMAND
176  std::atomic<uint32_t> m_lockCount;
177  std::atomic<bool> m_active;
178 #endif
179 };
180 
181 template<class T>
182 class Lockable
183 {
184 public:
186  : m_ctx( srcloc )
187  {
188  }
189 
190  Lockable( const Lockable& ) = delete;
191  Lockable& operator=( const Lockable& ) = delete;
192 
194  {
195  const auto runAfter = m_ctx.BeforeLock();
196  m_lockable.lock();
197  if( runAfter ) m_ctx.AfterLock();
198  }
199 
201  {
202  m_lockable.unlock();
203  m_ctx.AfterUnlock();
204  }
205 
207  {
208  const auto acquired = m_lockable.try_lock();
209  m_ctx.AfterTryLock( acquired );
210  return acquired;
211  }
212 
214  {
215  m_ctx.Mark( srcloc );
216  }
217 
218  tracy_force_inline void CustomName( const char* name, size_t size )
219  {
220  m_ctx.CustomName( name, size );
221  }
222 
223 private:
226 };
227 
228 
230 {
231 public:
233  : m_id( GetLockCounter().fetch_add( 1, std::memory_order_relaxed ) )
234 #ifdef TRACY_ON_DEMAND
235  , m_lockCount( 0 )
236  , m_active( false )
237 #endif
238  {
240 
241  auto item = Profiler::QueueSerial();
242  MemWrite( &item->hdr.type, QueueType::LockAnnounce );
243  MemWrite( &item->lockAnnounce.id, m_id );
244  MemWrite( &item->lockAnnounce.time, Profiler::GetTime() );
245  MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc );
246  MemWrite( &item->lockAnnounce.type, LockType::SharedLockable );
247 #ifdef TRACY_ON_DEMAND
248  GetProfiler().DeferItem( *item );
249 #endif
251  }
252 
253  SharedLockableCtx( const SharedLockableCtx& ) = delete;
254  SharedLockableCtx& operator=( const SharedLockableCtx& ) = delete;
255 
257  {
258  auto item = Profiler::QueueSerial();
259  MemWrite( &item->hdr.type, QueueType::LockTerminate );
260  MemWrite( &item->lockTerminate.id, m_id );
261  MemWrite( &item->lockTerminate.time, Profiler::GetTime() );
262 #ifdef TRACY_ON_DEMAND
263  GetProfiler().DeferItem( *item );
264 #endif
266  }
267 
269  {
270 #ifdef TRACY_ON_DEMAND
271  bool queue = false;
272  const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
273  const auto active = m_active.load( std::memory_order_relaxed );
274  if( locks == 0 || active )
275  {
276  const bool connected = GetProfiler().IsConnected();
277  if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
278  if( connected ) queue = true;
279  }
280  if( !queue ) return false;
281 #endif
282 
283  auto item = Profiler::QueueSerial();
284  MemWrite( &item->hdr.type, QueueType::LockWait );
285  MemWrite( &item->lockWait.thread, GetThreadHandle() );
286  MemWrite( &item->lockWait.id, m_id );
287  MemWrite( &item->lockWait.time, Profiler::GetTime() );
289  return true;
290  }
291 
293  {
294  auto item = Profiler::QueueSerial();
295  MemWrite( &item->hdr.type, QueueType::LockObtain );
296  MemWrite( &item->lockObtain.thread, GetThreadHandle() );
297  MemWrite( &item->lockObtain.id, m_id );
298  MemWrite( &item->lockObtain.time, Profiler::GetTime() );
300  }
301 
303  {
304 #ifdef TRACY_ON_DEMAND
305  m_lockCount.fetch_sub( 1, std::memory_order_relaxed );
306  if( !m_active.load( std::memory_order_relaxed ) ) return;
307  if( !GetProfiler().IsConnected() )
308  {
309  m_active.store( false, std::memory_order_relaxed );
310  return;
311  }
312 #endif
313 
314  auto item = Profiler::QueueSerial();
315  MemWrite( &item->hdr.type, QueueType::LockRelease );
316  MemWrite( &item->lockRelease.thread, GetThreadHandle() );
317  MemWrite( &item->lockRelease.id, m_id );
318  MemWrite( &item->lockRelease.time, Profiler::GetTime() );
320  }
321 
322  tracy_force_inline void AfterTryLock( bool acquired )
323  {
324 #ifdef TRACY_ON_DEMAND
325  if( !acquired ) return;
326 
327  bool queue = false;
328  const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
329  const auto active = m_active.load( std::memory_order_relaxed );
330  if( locks == 0 || active )
331  {
332  const bool connected = GetProfiler().IsConnected();
333  if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
334  if( connected ) queue = true;
335  }
336  if( !queue ) return;
337 #endif
338 
339  if( acquired )
340  {
341  auto item = Profiler::QueueSerial();
342  MemWrite( &item->hdr.type, QueueType::LockObtain );
343  MemWrite( &item->lockObtain.thread, GetThreadHandle() );
344  MemWrite( &item->lockObtain.id, m_id );
345  MemWrite( &item->lockObtain.time, Profiler::GetTime() );
347  }
348  }
349 
351  {
352 #ifdef TRACY_ON_DEMAND
353  bool queue = false;
354  const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
355  const auto active = m_active.load( std::memory_order_relaxed );
356  if( locks == 0 || active )
357  {
358  const bool connected = GetProfiler().IsConnected();
359  if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
360  if( connected ) queue = true;
361  }
362  if( !queue ) return false;
363 #endif
364 
365  auto item = Profiler::QueueSerial();
366  MemWrite( &item->hdr.type, QueueType::LockSharedWait );
367  MemWrite( &item->lockWait.thread, GetThreadHandle() );
368  MemWrite( &item->lockWait.id, m_id );
369  MemWrite( &item->lockWait.time, Profiler::GetTime() );
371  return true;
372  }
373 
375  {
376  auto item = Profiler::QueueSerial();
377  MemWrite( &item->hdr.type, QueueType::LockSharedObtain );
378  MemWrite( &item->lockObtain.thread, GetThreadHandle() );
379  MemWrite( &item->lockObtain.id, m_id );
380  MemWrite( &item->lockObtain.time, Profiler::GetTime() );
382  }
383 
385  {
386 #ifdef TRACY_ON_DEMAND
387  m_lockCount.fetch_sub( 1, std::memory_order_relaxed );
388  if( !m_active.load( std::memory_order_relaxed ) ) return;
389  if( !GetProfiler().IsConnected() )
390  {
391  m_active.store( false, std::memory_order_relaxed );
392  return;
393  }
394 #endif
395 
396  auto item = Profiler::QueueSerial();
397  MemWrite( &item->hdr.type, QueueType::LockSharedRelease );
398  MemWrite( &item->lockRelease.thread, GetThreadHandle() );
399  MemWrite( &item->lockRelease.id, m_id );
400  MemWrite( &item->lockRelease.time, Profiler::GetTime() );
402  }
403 
405  {
406 #ifdef TRACY_ON_DEMAND
407  if( !acquired ) return;
408 
409  bool queue = false;
410  const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed );
411  const auto active = m_active.load( std::memory_order_relaxed );
412  if( locks == 0 || active )
413  {
414  const bool connected = GetProfiler().IsConnected();
415  if( active != connected ) m_active.store( connected, std::memory_order_relaxed );
416  if( connected ) queue = true;
417  }
418  if( !queue ) return;
419 #endif
420 
421  if( acquired )
422  {
423  auto item = Profiler::QueueSerial();
424  MemWrite( &item->hdr.type, QueueType::LockSharedObtain );
425  MemWrite( &item->lockObtain.thread, GetThreadHandle() );
426  MemWrite( &item->lockObtain.id, m_id );
427  MemWrite( &item->lockObtain.time, Profiler::GetTime() );
429  }
430  }
431 
433  {
434 #ifdef TRACY_ON_DEMAND
435  const auto active = m_active.load( std::memory_order_relaxed );
436  if( !active ) return;
437  const auto connected = GetProfiler().IsConnected();
438  if( !connected )
439  {
440  if( active ) m_active.store( false, std::memory_order_relaxed );
441  return;
442  }
443 #endif
444 
445  auto item = Profiler::QueueSerial();
446  MemWrite( &item->hdr.type, QueueType::LockMark );
447  MemWrite( &item->lockMark.thread, GetThreadHandle() );
448  MemWrite( &item->lockMark.id, m_id );
449  MemWrite( &item->lockMark.srcloc, (uint64_t)srcloc );
451  }
452 
453  tracy_force_inline void CustomName( const char* name, size_t size )
454  {
455  assert( size < std::numeric_limits<uint16_t>::max() );
456  auto ptr = (char*)tracy_malloc( size );
457  memcpy( ptr, name, size );
458  auto item = Profiler::QueueSerial();
459  MemWrite( &item->hdr.type, QueueType::LockName );
460  MemWrite( &item->lockNameFat.id, m_id );
461  MemWrite( &item->lockNameFat.name, (uint64_t)ptr );
462  MemWrite( &item->lockNameFat.size, (uint16_t)size );
463 #ifdef TRACY_ON_DEMAND
464  GetProfiler().DeferItem( *item );
465 #endif
467  }
468 
469 private:
471 
472 #ifdef TRACY_ON_DEMAND
473  std::atomic<uint32_t> m_lockCount;
474  std::atomic<bool> m_active;
475 #endif
476 };
477 
478 template<class T>
480 {
481 public:
483  : m_ctx( srcloc )
484  {
485  }
486 
487  SharedLockable( const SharedLockable& ) = delete;
488  SharedLockable& operator=( const SharedLockable& ) = delete;
489 
491  {
492  const auto runAfter = m_ctx.BeforeLock();
493  m_lockable.lock();
494  if( runAfter ) m_ctx.AfterLock();
495  }
496 
498  {
499  m_lockable.unlock();
500  m_ctx.AfterUnlock();
501  }
502 
504  {
505  const auto acquired = m_lockable.try_lock();
506  m_ctx.AfterTryLock( acquired );
507  return acquired;
508  }
509 
511  {
512  const auto runAfter = m_ctx.BeforeLockShared();
513  m_lockable.lock_shared();
514  if( runAfter ) m_ctx.AfterLockShared();
515  }
516 
518  {
519  m_lockable.unlock_shared();
521  }
522 
524  {
525  const auto acquired = m_lockable.try_lock_shared();
526  m_ctx.AfterTryLockShared( acquired );
527  return acquired;
528  }
529 
531  {
532  m_ctx.Mark( srcloc );
533  }
534 
535  tracy_force_inline void CustomName( const char* name, size_t size )
536  {
537  m_ctx.CustomName( name, size );
538  }
539 
540 private:
543 };
544 
545 
546 }
547 
548 #endif


Copyright © 2005-2021 MAK Technologies. All Rights Reserved (www.mak.com)