diff options
| author | 2016-03-05 23:29:14 -0500 | |
|---|---|---|
| committer | 2016-03-05 23:29:14 -0500 | |
| commit | 8ee230fe1ca6392cc7c8a5456d77066b8ea2b866 (patch) | |
| tree | 8adb98476413e2e14cae7aa67c3567419df3ebf5 /src/core | |
| parent | Merge pull request #1459 from MerryMage/dsp-firmware-hash (diff) | |
| parent | core: Use unrestricted union to hold storage of ResultVal value (diff) | |
| download | yuzu-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/core')
| -rw-r--r-- | src/core/hle/result.h | 58 |
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 | ||
| 374 | private: | 369 | private: |
| 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 | /** |