• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Resource.hpp"
16 
17 #include "Memory.hpp"
18 
19 namespace sw
20 {
Resource(size_t bytes)21 	Resource::Resource(size_t bytes) : size(bytes)
22 	{
23 		blocked = 0;
24 
25 		accessor = PUBLIC;
26 		count = 0;
27 		orphaned = false;
28 
29 		buffer = allocate(bytes);
30 	}
31 
~Resource()32 	Resource::~Resource()
33 	{
34 		deallocate(buffer);
35 	}
36 
lock(Accessor claimer)37 	void *Resource::lock(Accessor claimer)
38 	{
39 		criticalSection.lock();
40 
41 		while(count > 0 && accessor != claimer)
42 		{
43 			blocked++;
44 			criticalSection.unlock();
45 
46 			unblock.wait();
47 
48 			criticalSection.lock();
49 			blocked--;
50 		}
51 
52 		accessor = claimer;
53 		count++;
54 
55 		criticalSection.unlock();
56 
57 		return buffer;
58 	}
59 
lock(Accessor relinquisher,Accessor claimer)60 	void *Resource::lock(Accessor relinquisher, Accessor claimer)
61 	{
62 		criticalSection.lock();
63 
64 		// Release
65 		while(count > 0 && accessor == relinquisher)
66 		{
67 			count--;
68 
69 			if(count == 0)
70 			{
71 				if(blocked)
72 				{
73 					unblock.signal();
74 				}
75 				else if(orphaned)
76 				{
77 					criticalSection.unlock();
78 
79 					delete this;
80 
81 					return 0;
82 				}
83 			}
84 		}
85 
86 		// Acquire
87 		while(count > 0 && accessor != claimer)
88 		{
89 			blocked++;
90 			criticalSection.unlock();
91 
92 			unblock.wait();
93 
94 			criticalSection.lock();
95 			blocked--;
96 		}
97 
98 		accessor = claimer;
99 		count++;
100 
101 		criticalSection.unlock();
102 
103 		return buffer;
104 	}
105 
unlock()106 	void Resource::unlock()
107 	{
108 		criticalSection.lock();
109 
110 		count--;
111 
112 		if(count == 0)
113 		{
114 			if(blocked)
115 			{
116 				unblock.signal();
117 			}
118 			else if(orphaned)
119 			{
120 				criticalSection.unlock();
121 
122 				delete this;
123 
124 				return;
125 			}
126 		}
127 
128 		criticalSection.unlock();
129 	}
130 
unlock(Accessor relinquisher)131 	void Resource::unlock(Accessor relinquisher)
132 	{
133 		criticalSection.lock();
134 
135 		while(count > 0 && accessor == relinquisher)
136 		{
137 			count--;
138 
139 			if(count == 0)
140 			{
141 				if(blocked)
142 				{
143 					unblock.signal();
144 				}
145 				else if(orphaned)
146 				{
147 					criticalSection.unlock();
148 
149 					delete this;
150 
151 					return;
152 				}
153 			}
154 		}
155 
156 		criticalSection.unlock();
157 	}
158 
destruct()159 	void Resource::destruct()
160 	{
161 		criticalSection.lock();
162 
163 		if(count == 0 && !blocked)
164 		{
165 			criticalSection.unlock();
166 
167 			delete this;
168 
169 			return;
170 		}
171 
172 		orphaned = true;
173 
174 		criticalSection.unlock();
175 	}
176 
data() const177 	const void *Resource::data() const
178 	{
179 		return buffer;
180 	}
181 }
182