Bootstrap.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/crt/Api.h>
  6. #include <aws/crt/io/Bootstrap.h>
  7. namespace Aws
  8. {
  9. namespace Crt
  10. {
  11. namespace Io
  12. {
  13. /**
  14. * @private
  15. * Holds the bootstrap's shutdown promise.
  16. * Lives until the bootstrap's shutdown-complete callback fires.
  17. */
  18. class ClientBootstrapCallbackData
  19. {
  20. private:
  21. Allocator *m_allocator;
  22. public:
  23. ClientBootstrapCallbackData(Allocator *allocator) : m_allocator(allocator) {}
  24. /**
  25. * Promise for bootstrap's shutdown.
  26. */
  27. std::promise<void> ShutdownPromise;
  28. /**
  29. * User callback of bootstrap's shutdown-complete.
  30. */
  31. OnClientBootstrapShutdownComplete ShutdownCallback;
  32. /**
  33. * Internal callback of bootstrap's shutdown-complete
  34. */
  35. static void OnShutdownComplete(void *userData)
  36. {
  37. auto callbackData = static_cast<ClientBootstrapCallbackData *>(userData);
  38. callbackData->ShutdownPromise.set_value();
  39. if (callbackData->ShutdownCallback)
  40. {
  41. callbackData->ShutdownCallback();
  42. }
  43. Crt::Delete(callbackData, callbackData->m_allocator);
  44. }
  45. };
  46. ClientBootstrap::ClientBootstrap(
  47. EventLoopGroup &elGroup,
  48. HostResolver &resolver,
  49. Allocator *allocator) noexcept
  50. : m_bootstrap(nullptr), m_lastError(AWS_ERROR_SUCCESS),
  51. m_callbackData(Crt::New<ClientBootstrapCallbackData>(allocator, allocator)),
  52. m_enableBlockingShutdown(false)
  53. {
  54. m_shutdownFuture = m_callbackData->ShutdownPromise.get_future();
  55. aws_client_bootstrap_options options;
  56. options.event_loop_group = elGroup.GetUnderlyingHandle();
  57. options.host_resolution_config = resolver.GetConfig();
  58. options.host_resolver = resolver.GetUnderlyingHandle();
  59. options.on_shutdown_complete = ClientBootstrapCallbackData::OnShutdownComplete;
  60. options.user_data = m_callbackData.get();
  61. m_bootstrap = aws_client_bootstrap_new(allocator, &options);
  62. if (!m_bootstrap)
  63. {
  64. m_lastError = aws_last_error();
  65. }
  66. }
  67. ClientBootstrap::ClientBootstrap(Allocator *allocator) noexcept
  68. : ClientBootstrap(
  69. *Crt::ApiHandle::GetOrCreateStaticDefaultEventLoopGroup(),
  70. *Crt::ApiHandle::GetOrCreateStaticDefaultHostResolver(),
  71. allocator)
  72. {
  73. }
  74. ClientBootstrap::~ClientBootstrap()
  75. {
  76. if (m_bootstrap)
  77. {
  78. // Release m_callbackData, it destroys itself when shutdown completes.
  79. m_callbackData.release();
  80. aws_client_bootstrap_release(m_bootstrap);
  81. if (m_enableBlockingShutdown)
  82. {
  83. // If your program is stuck here, stop using EnableBlockingShutdown()
  84. m_shutdownFuture.wait();
  85. }
  86. }
  87. }
  88. ClientBootstrap::operator bool() const noexcept { return m_lastError == AWS_ERROR_SUCCESS; }
  89. int ClientBootstrap::LastError() const noexcept { return m_lastError; }
  90. void ClientBootstrap::SetShutdownCompleteCallback(OnClientBootstrapShutdownComplete callback)
  91. {
  92. m_callbackData->ShutdownCallback = std::move(callback);
  93. }
  94. void ClientBootstrap::EnableBlockingShutdown() noexcept { m_enableBlockingShutdown = true; }
  95. aws_client_bootstrap *ClientBootstrap::GetUnderlyingHandle() const noexcept
  96. {
  97. if (*this)
  98. {
  99. return m_bootstrap;
  100. }
  101. return nullptr;
  102. }
  103. } // namespace Io
  104. } // namespace Crt
  105. } // namespace Aws