promise.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/common/condition_variable.h>
  6. #include <aws/common/mutex.h>
  7. #include <aws/common/promise.h>
  8. #include <aws/common/ref_count.h>
  9. struct aws_promise {
  10. struct aws_allocator *allocator;
  11. struct aws_mutex mutex;
  12. struct aws_condition_variable cv;
  13. struct aws_ref_count rc;
  14. bool complete;
  15. int error_code;
  16. void *value;
  17. /* destructor for value, will be invoked if the value is not taken */
  18. void (*dtor)(void *);
  19. };
  20. static void s_aws_promise_dtor(void *ptr) {
  21. struct aws_promise *promise = ptr;
  22. aws_condition_variable_clean_up(&promise->cv);
  23. aws_mutex_clean_up(&promise->mutex);
  24. if (promise->value && promise->dtor) {
  25. promise->dtor(promise->value);
  26. }
  27. aws_mem_release(promise->allocator, promise);
  28. }
  29. struct aws_promise *aws_promise_new(struct aws_allocator *allocator) {
  30. struct aws_promise *promise = aws_mem_calloc(allocator, 1, sizeof(struct aws_promise));
  31. promise->allocator = allocator;
  32. aws_ref_count_init(&promise->rc, promise, s_aws_promise_dtor);
  33. aws_mutex_init(&promise->mutex);
  34. aws_condition_variable_init(&promise->cv);
  35. return promise;
  36. }
  37. struct aws_promise *aws_promise_acquire(struct aws_promise *promise) {
  38. aws_ref_count_acquire(&promise->rc);
  39. return promise;
  40. }
  41. void aws_promise_release(struct aws_promise *promise) {
  42. aws_ref_count_release(&promise->rc);
  43. }
  44. static bool s_promise_completed(void *user_data) {
  45. struct aws_promise *promise = user_data;
  46. return promise->complete;
  47. }
  48. void aws_promise_wait(struct aws_promise *promise) {
  49. aws_mutex_lock(&promise->mutex);
  50. aws_condition_variable_wait_pred(&promise->cv, &promise->mutex, s_promise_completed, promise);
  51. aws_mutex_unlock(&promise->mutex);
  52. }
  53. bool aws_promise_wait_for(struct aws_promise *promise, size_t nanoseconds) {
  54. aws_mutex_lock(&promise->mutex);
  55. aws_condition_variable_wait_for_pred(
  56. &promise->cv, &promise->mutex, (int64_t)nanoseconds, s_promise_completed, promise);
  57. const bool complete = promise->complete;
  58. aws_mutex_unlock(&promise->mutex);
  59. return complete;
  60. }
  61. bool aws_promise_is_complete(struct aws_promise *promise) {
  62. aws_mutex_lock(&promise->mutex);
  63. const bool complete = promise->complete;
  64. aws_mutex_unlock(&promise->mutex);
  65. return complete;
  66. }
  67. void aws_promise_complete(struct aws_promise *promise, void *value, void (*dtor)(void *)) {
  68. aws_mutex_lock(&promise->mutex);
  69. AWS_FATAL_ASSERT(!promise->complete && "aws_promise_complete: cannot complete a promise more than once");
  70. promise->value = value;
  71. promise->dtor = dtor;
  72. promise->complete = true;
  73. aws_mutex_unlock(&promise->mutex);
  74. aws_condition_variable_notify_all(&promise->cv);
  75. }
  76. void aws_promise_fail(struct aws_promise *promise, int error_code) {
  77. AWS_FATAL_ASSERT(error_code != 0 && "aws_promise_fail: cannot fail a promise with a 0 error_code");
  78. aws_mutex_lock(&promise->mutex);
  79. AWS_FATAL_ASSERT(!promise->complete && "aws_promise_fail: cannot complete a promise more than once");
  80. promise->error_code = error_code;
  81. promise->complete = true;
  82. aws_mutex_unlock(&promise->mutex);
  83. aws_condition_variable_notify_all(&promise->cv);
  84. }
  85. int aws_promise_error_code(struct aws_promise *promise) {
  86. AWS_FATAL_ASSERT(aws_promise_is_complete(promise));
  87. return promise->error_code;
  88. }
  89. void *aws_promise_value(struct aws_promise *promise) {
  90. AWS_FATAL_ASSERT(aws_promise_is_complete(promise));
  91. return promise->value;
  92. }
  93. void *aws_promise_take_value(struct aws_promise *promise) {
  94. AWS_FATAL_ASSERT(aws_promise_is_complete(promise));
  95. void *value = promise->value;
  96. promise->value = NULL;
  97. promise->dtor = NULL;
  98. return value;
  99. }