summaryrefslogtreecommitdiff
path: root/Source/modules/asura-base/Threads/Conditional.cpp
blob: f86a81e4a56342041974319321b9ffd7c951b9cc (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
#include "Conditional.h"

namespace_begin(AsuraEngine)
namespace_begin(Threads)

Conditional::Conditional()
	: m_Waiting(0)
	, m_Signals(0)
{
}

Conditional::~Conditional()
{
}

void Conditional::Signal()
{
	m_Mutex.Lock(); 
	if (m_Waiting > m_Signals)
	{
		++m_Signals;
		signal(m_WaitSem);
		m_Mutex.Unlock(); 
		wait(m_DoneSem);
	}
	else
	{
		m_Mutex.Unlock();
	}
}

void Conditional::Broadcast()
{
	m_Mutex.Lock();
	if (m_Waiting> m_Signals) {
		int i, num_waiting;

		num_waiting = (m_Waiting - m_Signals);
		m_Signals = m_Waiting;
		for (i = 0; i < num_waiting; ++i) {
			signal(m_WaitSem);
		}
		m_Mutex.Unlock();
		for (i = 0; i < num_waiting; ++i) {
			wait(m_DoneSem);
		}
	}
	else {
		m_Mutex.Unlock();
	}

}

bool Conditional::Wait(Mutex* mutex, int timeout /*= ASURA_MUTEX_MAXWAIT*/)
{
	bool retval;

	m_Mutex.Lock();
	++m_Waiting;
	m_Mutex.Unlock();

	mutex->Unlock();

	retval = wait(m_WaitSem, timeout);

	m_Mutex.Lock();
	if (m_Signals > 0) {
		if (!retval) {
			wait(m_WaitSem);
		}
		signal(m_DoneSem);

		--m_Signals;
	}
	--m_Waiting;
	m_Mutex.Unlock();

	m_Mutex.Lock();

	return retval;
}

namespace_end
namespace_end