Programación asíncrona mediante AWS SDK para C++ - AWS SDK para C++

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Programación asíncrona mediante AWS SDK para C++

Métodos de SDK asíncronos

Para muchos métodos, el SDK para C++ proporciona versiones sincrónicas y asíncronas. Un método es asíncrono si incluye el sufijo en su nombre. Async Por ejemplo, el método Amazon S3 PutObject es sincrónico y PutObjectAsync asíncrono.

Como todas las operaciones asíncronas, un método SDK asíncrono regresa antes de que finalice su tarea principal. Por ejemplo, el PutObjectAsync método regresa antes de terminar de cargar el archivo en el bucket de Amazon S3. Mientras continúa la operación de carga, la aplicación puede realizar otras operaciones, incluida la llamada a otros métodos asíncronos. La aplicación recibe una notificación de que una operación asíncrona ha finalizado cuando se invoca una función de devolución de llamada asociada.

En las siguientes secciones se describe un ejemplo de código que muestra la llamada al método asíncrono. PutObjectAsync Cada sección se centra en partes individuales del archivo fuente completo del ejemplo.

Llamar a métodos asíncronos del SDK

En general, la versión asíncrona de un método del SDK acepta los siguientes argumentos.

  • Una referencia al mismo objeto de tipo Request que su homólogo sincrónico.

  • Referencia a una función de devolución de llamada del controlador de respuestas. Esta función de devolución de llamada se invoca cuando finaliza la operación asíncrona. Uno de los argumentos contiene el resultado de la operación.

  • Opcional shared_ptr para un AsyncCallerContext objeto. El objeto se pasa al callback del controlador de respuestas. Incluye una propiedad UUID que se puede usar para pasar información de texto a la devolución de llamada.

El uploadFileAsync método que se muestra a continuación configura y llama al PutObjectAsync método Amazon S3 del SDK para cargar de forma asíncrona un archivo a un bucket de Amazon S3.

La función recibe referencias a un S3Client objeto y a un objeto. PutObjectRequest Las recibe de la función principal porque debemos asegurarnos de que estos objetos existan durante las llamadas asíncronas.

Se asigna A shared_ptr a un AsyncCallerContext objeto. Su UUID propiedad se establece en el nombre del objeto de Amazon S3. Con fines de demostración, el callback del controlador de respuestas accede a la propiedad y genera su valor.

La llamada a PutObjectAsync incluye un argumento de referencia a la función de devolución de llamada del controlador de respuestas. uploadFileAsyncFinished Esta función de devolución de llamada se examina con más detalle en la siguiente sección.

bool AwsDoc::S3::uploadFileAsync(const Aws::S3::S3Client &s3Client, Aws::S3::Model::PutObjectRequest &request, const Aws::String &bucketName, const Aws::String &fileName) { request.SetBucket(bucketName); request.SetKey(fileName); const std::shared_ptr<Aws::IOStream> input_data = Aws::MakeShared<Aws::FStream>("SampleAllocationTag", fileName.c_str(), std::ios_base::in | std::ios_base::binary); if (!*input_data) { std::cerr << "Error: unable to open file " << fileName << std::endl; return false; } request.SetBody(input_data); // Create and configure the context for the asynchronous put object request. std::shared_ptr<Aws::Client::AsyncCallerContext> context = Aws::MakeShared<Aws::Client::AsyncCallerContext>("PutObjectAllocationTag"); context->SetUUID(fileName); // Make the asynchronous put object call. Queue the request into a // thread executor and call the uploadFileAsyncFinished function when the // operation has finished. s3Client.PutObjectAsync(request, uploadFileAsyncFinished, context); return true; }

Los recursos para una operación asíncrona deben existir hasta que finalice la operación. Por ejemplo, los objetos cliente y de solicitud deben existir hasta que la aplicación reciba la notificación de que la operación se ha completado. La aplicación en sí misma no puede finalizar hasta que se complete la operación asíncrona.

Por este motivo, el uploadFileAsync método acepta referencias a PutObjectRequest objetos S3Client y en lugar de crearlos en el uploadFileAsync método y almacenarlos en una variable local.

En el ejemplo, el PutObjectAsync método vuelve a la persona que llama inmediatamente después de iniciar la operación asíncrona, lo que permite a la cadena de llamada realizar tareas adicionales mientras la operación de carga está en curso.

Si el cliente estuviera almacenado en una variable local del uploadFileAsync método, quedaría fuera del alcance cuando el método regresara. Sin embargo, el objeto cliente debe seguir existiendo hasta que finalice la operación asincrónica.

Notificación de la finalización de una operación asíncrona

Cuando finaliza una operación asíncrona, se invoca una función de devolución de llamada del controlador de respuestas de la aplicación. Esta notificación incluye el resultado de la operación. El resultado está contenido en la misma clase de tipo Resultado devuelta por la contraparte síncrona del método. En el ejemplo de código, el resultado está en un objeto. PutObjectOutcome

La función de devolución de llamada del controlador de respuestas del ejemplo uploadFileAsyncFinished se muestra a continuación. Comprueba si la operación asíncrona se realizó correctamente o falló. Utiliza std::condition_variable a para notificar al subproceso de la aplicación que la operación asíncrona ha finalizado.

// A mutex is a synchronization primitive that can be used to protect shared // data from being simultaneously accessed by multiple threads. std::mutex AwsDoc::S3::upload_mutex; // A condition_variable is a synchronization primitive that can be used to // block a thread, or to block multiple threads at the same time. // The thread is blocked until another thread both modifies a shared // variable (the condition) and notifies the condition_variable. std::condition_variable AwsDoc::S3::upload_variable;
void uploadFileAsyncFinished(const Aws::S3::S3Client *s3Client, const Aws::S3::Model::PutObjectRequest &request, const Aws::S3::Model::PutObjectOutcome &outcome, const std::shared_ptr<const Aws::Client::AsyncCallerContext> &context) { if (outcome.IsSuccess()) { std::cout << "Success: uploadFileAsyncFinished: Finished uploading '" << context->GetUUID() << "'." << std::endl; } else { std::cerr << "Error: uploadFileAsyncFinished: " << outcome.GetError().GetMessage() << std::endl; } // Unblock the thread that is waiting for this function to complete. AwsDoc::S3::upload_variable.notify_one(); }

Una vez finalizada la operación asíncrona, se pueden liberar los recursos asociados a ella. La aplicación también puede finalizar si lo desea.

El siguiente código muestra cómo una aplicación utiliza los uploadFileAsyncFinished métodos uploadFileAsync y.

La aplicación asigna los PutObjectRequest objetos S3Client y para que sigan existiendo hasta que finalice la operación asíncrona. Tras la llamadauploadFileAsync, la aplicación puede realizar las operaciones que desee. Para simplificar, en el ejemplo se utiliza una std::mutex y std::condition_variable para esperar a que la llamada del controlador de respuestas le notifique que la operación de carga ha finalizado.

int main(int argc, char* argv[]) { if (argc != 3) { std::cout << R"( Usage: run_put_object_async <file_name> <bucket_name> Where: file_name - The name of the file to upload. bucket_name - The name of the bucket to upload the object to. )" << std::endl; return 1; } const Aws::SDKOptions options; Aws::InitAPI(options); { const Aws::String fileName = argv[1]; const Aws::String bucketName = argv[2]; // A unique_lock is a general-purpose mutex ownership wrapper allowing // deferred locking, time-constrained attempts at locking, recursive // locking, transfer of lock ownership, and use with // condition variables. std::unique_lock<std::mutex> lock(AwsDoc::S3::upload_mutex); // Create and configure the Amazon S3 client. // This client must be declared here, as this client must exist // until the put object operation finishes. const Aws::S3::S3ClientConfiguration config; // Optional: Set to the AWS Region in which the bucket was created (overrides config file). // config.region = "us-east-1"; const Aws::S3::S3Client s3Client(config); // Create the request object. // This request object must be declared here, because the object must exist // until the put object operation finishes. Aws::S3::Model::PutObjectRequest request; AwsDoc::S3::uploadFileAsync(s3Client, request, bucketName, fileName); std::cout << "main: Waiting for file upload attempt..." << std::endl << std::endl; // While the put object operation attempt is in progress, // you can perform other tasks. // This example simply blocks until the put object operation // attempt finishes. AwsDoc::S3::upload_variable.wait(lock); std::cout << std::endl << "main: File upload attempt completed." << std::endl; } Aws::ShutdownAPI(options); return 0; }

Consulte el ejemplo completo en Github.