condition_variable.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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/clock.h>
  7. #include <aws/common/mutex.h>
  8. #include <errno.h>
  9. static int process_error_code(int err) {
  10. switch (err) {
  11. case ENOMEM:
  12. return aws_raise_error(AWS_ERROR_OOM);
  13. case ETIMEDOUT:
  14. return aws_raise_error(AWS_ERROR_COND_VARIABLE_TIMED_OUT);
  15. default:
  16. return aws_raise_error(AWS_ERROR_COND_VARIABLE_ERROR_UNKNOWN);
  17. }
  18. }
  19. int aws_condition_variable_init(struct aws_condition_variable *condition_variable) {
  20. AWS_PRECONDITION(condition_variable);
  21. if (pthread_cond_init(&condition_variable->condition_handle, NULL)) {
  22. AWS_ZERO_STRUCT(*condition_variable);
  23. return aws_raise_error(AWS_ERROR_COND_VARIABLE_INIT_FAILED);
  24. }
  25. condition_variable->initialized = true;
  26. return AWS_OP_SUCCESS;
  27. }
  28. void aws_condition_variable_clean_up(struct aws_condition_variable *condition_variable) {
  29. AWS_PRECONDITION(condition_variable);
  30. if (condition_variable->initialized) {
  31. pthread_cond_destroy(&condition_variable->condition_handle);
  32. }
  33. AWS_ZERO_STRUCT(*condition_variable);
  34. }
  35. int aws_condition_variable_notify_one(struct aws_condition_variable *condition_variable) {
  36. AWS_PRECONDITION(condition_variable && condition_variable->initialized);
  37. int err_code = pthread_cond_signal(&condition_variable->condition_handle);
  38. if (err_code) {
  39. return process_error_code(err_code);
  40. }
  41. return AWS_OP_SUCCESS;
  42. }
  43. int aws_condition_variable_notify_all(struct aws_condition_variable *condition_variable) {
  44. AWS_PRECONDITION(condition_variable && condition_variable->initialized);
  45. int err_code = pthread_cond_broadcast(&condition_variable->condition_handle);
  46. if (err_code) {
  47. return process_error_code(err_code);
  48. }
  49. return AWS_OP_SUCCESS;
  50. }
  51. int aws_condition_variable_wait(struct aws_condition_variable *condition_variable, struct aws_mutex *mutex) {
  52. AWS_PRECONDITION(condition_variable && condition_variable->initialized);
  53. AWS_PRECONDITION(mutex && mutex->initialized);
  54. int err_code = pthread_cond_wait(&condition_variable->condition_handle, &mutex->mutex_handle);
  55. if (err_code) {
  56. return process_error_code(err_code);
  57. }
  58. return AWS_OP_SUCCESS;
  59. }
  60. int aws_condition_variable_wait_for(
  61. struct aws_condition_variable *condition_variable,
  62. struct aws_mutex *mutex,
  63. int64_t time_to_wait) {
  64. AWS_PRECONDITION(condition_variable && condition_variable->initialized);
  65. AWS_PRECONDITION(mutex && mutex->initialized);
  66. uint64_t current_sys_time = 0;
  67. if (aws_sys_clock_get_ticks(&current_sys_time)) {
  68. return AWS_OP_ERR;
  69. }
  70. time_to_wait += current_sys_time;
  71. struct timespec ts;
  72. uint64_t remainder = 0;
  73. ts.tv_sec =
  74. (time_t)aws_timestamp_convert((uint64_t)time_to_wait, AWS_TIMESTAMP_NANOS, AWS_TIMESTAMP_SECS, &remainder);
  75. ts.tv_nsec = (long)remainder;
  76. int err_code = pthread_cond_timedwait(&condition_variable->condition_handle, &mutex->mutex_handle, &ts);
  77. if (err_code) {
  78. return process_error_code(err_code);
  79. }
  80. return AWS_OP_SUCCESS;
  81. }