summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Mathew Maidment2016-03-05 23:29:14 -0500
committerGravatar Mathew Maidment2016-03-05 23:29:14 -0500
commit8ee230fe1ca6392cc7c8a5456d77066b8ea2b866 (patch)
tree8adb98476413e2e14cae7aa67c3567419df3ebf5 /src
parentMerge pull request #1459 from MerryMage/dsp-firmware-hash (diff)
parentcore: Use unrestricted union to hold storage of ResultVal value (diff)
downloadyuzu-8ee230fe1ca6392cc7c8a5456d77066b8ea2b866.tar.gz
yuzu-8ee230fe1ca6392cc7c8a5456d77066b8ea2b866.tar.xz
yuzu-8ee230fe1ca6392cc7c8a5456d77066b8ea2b866.zip
Merge pull request #1455 from yuriks/ResultVal-union
core: Use unrestricted union to hold storage of ResultVal value
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/result.h58
1 files changed, 16 insertions, 42 deletions
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 0fce5988b..69613fbbb 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -269,7 +269,6 @@ public:
269 : result_code(error_code) 269 : result_code(error_code)
270 { 270 {
271 ASSERT(error_code.IsError()); 271 ASSERT(error_code.IsError());
272 UpdateDebugPtr();
273 } 272 }
274 273
275 /** 274 /**
@@ -287,40 +286,37 @@ public:
287 : result_code(o.result_code) 286 : result_code(o.result_code)
288 { 287 {
289 if (!o.empty()) { 288 if (!o.empty()) {
290 new (&storage) T(*o.GetPointer()); 289 new (&object) T(o.object);
291 } 290 }
292 UpdateDebugPtr();
293 } 291 }
294 292
295 ResultVal(ResultVal&& o) 293 ResultVal(ResultVal&& o)
296 : result_code(o.result_code) 294 : result_code(o.result_code)
297 { 295 {
298 if (!o.empty()) { 296 if (!o.empty()) {
299 new (&storage) T(std::move(*o.GetPointer())); 297 new (&object) T(std::move(o.object));
300 } 298 }
301 UpdateDebugPtr();
302 } 299 }
303 300
304 ~ResultVal() { 301 ~ResultVal() {
305 if (!empty()) { 302 if (!empty()) {
306 GetPointer()->~T(); 303 object.~T();
307 } 304 }
308 } 305 }
309 306
310 ResultVal& operator=(const ResultVal& o) { 307 ResultVal& operator=(const ResultVal& o) {
311 if (!empty()) { 308 if (!empty()) {
312 if (!o.empty()) { 309 if (!o.empty()) {
313 *GetPointer() = *o.GetPointer(); 310 object = o.object;
314 } else { 311 } else {
315 GetPointer()->~T(); 312 object.~T();
316 } 313 }
317 } else { 314 } else {
318 if (!o.empty()) { 315 if (!o.empty()) {
319 new (&storage) T(*o.GetPointer()); 316 new (&object) T(o.object);
320 } 317 }
321 } 318 }
322 result_code = o.result_code; 319 result_code = o.result_code;
323 UpdateDebugPtr();
324 320
325 return *this; 321 return *this;
326 } 322 }
@@ -333,11 +329,10 @@ public:
333 void emplace(ResultCode success_code, Args&&... args) { 329 void emplace(ResultCode success_code, Args&&... args) {
334 ASSERT(success_code.IsSuccess()); 330 ASSERT(success_code.IsSuccess());
335 if (!empty()) { 331 if (!empty()) {
336 GetPointer()->~T(); 332 object.~T();
337 } 333 }
338 new (&storage) T(std::forward<Args>(args)...); 334 new (&object) T(std::forward<Args>(args)...);
339 result_code = success_code; 335 result_code = success_code;
340 UpdateDebugPtr();
341 } 336 }
342 337
343 /// Returns true if the `ResultVal` contains an error code and no value. 338 /// Returns true if the `ResultVal` contains an error code and no value.
@@ -350,15 +345,15 @@ public:
350 345
351 ResultCode Code() const { return result_code; } 346 ResultCode Code() const { return result_code; }
352 347
353 const T& operator* () const { return *GetPointer(); } 348 const T& operator* () const { return object; }
354 T& operator* () { return *GetPointer(); } 349 T& operator* () { return object; }
355 const T* operator->() const { return GetPointer(); } 350 const T* operator->() const { return &object; }
356 T* operator->() { return GetPointer(); } 351 T* operator->() { return &object; }
357 352
358 /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing. 353 /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
359 template <typename U> 354 template <typename U>
360 T ValueOr(U&& value) const { 355 T ValueOr(U&& value) const {
361 return !empty() ? *GetPointer() : std::move(value); 356 return !empty() ? object : std::move(value);
362 } 357 }
363 358
364 /// Asserts that the result succeeded and returns a reference to it. 359 /// Asserts that the result succeeded and returns a reference to it.
@@ -372,31 +367,10 @@ public:
372 } 367 }
373 368
374private: 369private:
375 typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType; 370 // A union is used to allocate the storage for the value, while allowing us to construct and
376 371 // destruct it at will.
377 StorageType storage; 372 union { T object; };
378 ResultCode result_code; 373 ResultCode result_code;
379#ifdef _DEBUG
380 // The purpose of this pointer is to aid inspecting the type with a debugger, eliminating the
381 // need to cast `storage` to a pointer or pay attention to `result_code`.
382 const T* debug_ptr;
383#endif
384
385 void UpdateDebugPtr() {
386#ifdef _DEBUG
387 debug_ptr = empty() ? nullptr : static_cast<const T*>(static_cast<const void*>(&storage));
388#endif
389 }
390
391 const T* GetPointer() const {
392 ASSERT(!empty());
393 return static_cast<const T*>(static_cast<const void*>(&storage));
394 }
395
396 T* GetPointer() {
397 ASSERT(!empty());
398 return static_cast<T*>(static_cast<void*>(&storage));
399 }
400}; 374};
401 375
402/** 376/**