summaryrefslogtreecommitdiff
path: root/Runtime/Threads/ProfilerMutex.h
blob: 1e82b7c42087c1341f40364b0be3f2c4f0a62e98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifndef __PROFILERMUTEX_H
#define __PROFILERMUTEX_H

#include "Mutex.h"

#if ENABLE_PROFILER
#include "Runtime/Profiler/Profiler.h"
#endif

#define THREAD_LOCK_WARNINGS 0
#define THREAD_LOCK_TIMING 0

#if THREAD_LOCK_WARNINGS || (ENABLE_PROFILER && SUPPORT_THREADS)

#define AQUIRE_AUTOLOCK(mutex,profilerInformation) ProfilerMutexAutoLock aquireAutoLock (mutex, #mutex, profilerInformation, __FILE__, __LINE__)
#define AQUIRE_AUTOLOCK_WARN_MAIN_THREAD(mutex,profilerInformation) ProfilerMutexAutoLock aquireAutoLock (mutex, #mutex, Thread::mainThreadId, profilerInformation, __FILE__, __LINE__)
#define LOCK_MUTEX(mutex,profilerInformation) ProfilerMutexLock(mutex,#mutex,profilerInformation,__FILE__,__LINE__)

double GetTimeSinceStartup ();

inline void ProfilerMutexLock (Mutex& mutex, char const* mutexName, ProfilerInformation& information, char const* file, int line)
{
#if ENABLE_PROFILER || THREAD_LOCK_WARNINGS

	if (mutex.TryLock())
		return;

	#if THREAD_LOCK_WARNINGS
	DebugStringToFile (std::string ("Mutex '") + mutexName + "' already locked: " + information.name, 0, file, line, kScriptingWarning);
	#endif

	PROFILER_AUTO_THREAD_SAFE(information, NULL)

#if THREAD_LOCK_TIMING
	double start = GetTimeSinceStartup ();
	while (!mutex.TryLock())
		Sleep (10);

	double duration = GetTimeSinceStartup () - start;
	DebugStringToFile (std::string ("Mutex '") + mutexName + "' obtained after: " + FloatToString(duration, "%6.3f") + " s", 0, file, line, kScriptingWarning);
#else
	mutex.Lock();
#endif

#else
	mutex.Lock();
#endif
}

inline void ProfilerMutexLock (Mutex& mutex, char const* mutexName, Thread::ThreadID threadID, ProfilerInformation& information, char const* file, int line)
{
#if ENABLE_PROFILER || THREAD_LOCK_WARNINGS
	if (mutex.TryLock())
		return;
	
	#if THREAD_LOCK_WARNINGS
	if (Thread::EqualsCurrentThreadID(threadID))
	{
		DebugStringToFile (std::string ("Mutex '") + mutexName + "' already locked: " + information.name, 0, file, line, kScriptingWarning);
	}	
	#endif
	
	PROFILER_AUTO_THREAD_SAFE(information, NULL)

#if THREAD_LOCK_TIMING
	double start = GetTimeSinceStartup ();
	while (!mutex.TryLock())
		Sleep (10);

	double duration = GetTimeSinceStartup () - start;
	DebugStringToFile (std::string ("Mutex '") + mutexName + "' obtained after: " + FloatToString(duration, "%6.3f") + " s", 0, file, line, kScriptingWarning);
#else
	mutex.Lock();
#endif

#else
	mutex.Lock();
#endif
}

class ProfilerMutexAutoLock
{
public:
	ProfilerMutexAutoLock (Mutex& mutex, char const* mutexName, ProfilerInformation& profilerInformation, char const* file, int line)
	:	m_Mutex (&mutex)
	{
		ProfilerMutexLock(mutex, mutexName, profilerInformation, file, line);
	}

	ProfilerMutexAutoLock (Mutex& mutex, char const* mutexName, Thread::ThreadID threadID, ProfilerInformation& profilerInformation, char const* file, int line)
	:	m_Mutex (&mutex)
	{
		ProfilerMutexLock(mutex, mutexName, threadID, profilerInformation, file, line);
	}
	
	~ProfilerMutexAutoLock()
	{
		m_Mutex->Unlock();
	}
	
private:
	ProfilerMutexAutoLock(const ProfilerMutexAutoLock&);
	ProfilerMutexAutoLock& operator=(const ProfilerMutexAutoLock&);
	
private:
	Mutex*	m_Mutex;
};

#else

#define AQUIRE_AUTOLOCK(mutex,profilerInformation) Mutex::AutoLock aquireAutoLock (mutex)
#define AQUIRE_AUTOLOCK_WARN_MAIN_THREAD(mutex,profilerInformation) Mutex::AutoLock aquireAutoLock (mutex)
#define LOCK_MUTEX(mutex,profilerInformation) (mutex).Lock ()


#endif

#endif