강좌

C++ 코루틴(coroutine) 활용 강좌: #3 : co_return

하늘흐늘 2022. 5. 23. 15:32
반응형

이번 강좌는 co_await를 이용하여 함수 중간에 제어권을 다른 쪽으로 넘기다가 코루틴 함수의 끝에 co_return으로 값을 리턴하는 예제를 살펴보도록 하겠습니다. 예제는 실행 중간에 실행권을 멈추고 제어권을 다른 쪽으로 넘기면서 실행되다가 코루팀 함수의 끝에 값을 co_return으로 리턴하고 종료하는 코루틴 함수 A와 B를 보여주고 있습니다. C++ 코루틴(coroutine) 활용 강좌: #2 : co_await의 예제와 내용이 비슷한데 co_return으로 값을 리턴하고 코루틴 함수가 종료된다는 것만 틀립니다. 

예제 코드는 아래와 같습니다.

#include <iostream>
#include <coroutine>
#include <concepts>
#include <exception>


using namespace std;

template<typename T>
struct cotask_return {
	struct promise_type;
	using handle_type = std::coroutine_handle<promise_type>;

	struct promise_type {
		T return_value_;
		std::exception_ptr exception_;

		cotask_return get_return_object() {
			return cotask_return(handle_type::from_promise(*this));
		}
		std::suspend_always initial_suspend() { return {}; }
		std::suspend_always final_suspend() noexcept { return {}; }
		void unhandled_exception() { exception_ = std::current_exception(); }

		template<std::convertible_to<T> From>
		void return_value(From&& from)
		{
			return_value_ = std::forward<From>(from);
		}
	};

	handle_type handler_;

	cotask_return(handle_type handler) : handler_(handler) {}
	~cotask_return()
	{
		handler_.destroy();
	}

	bool done() {
		return handler_.done();
	}

	void operator()() {
		handler_();
		if (handler_.promise().exception_)
			std::rethrow_exception(handler_.promise().exception_);
	}

	T return_value()
	{
		return handler_.promise().return_value_;
	}
};

cotask_return<int> cotask_func_ra()
{
	cout << "cotask_func_ra 01" << endl;
	co_await std::suspend_always();
	cout << "cotask_func_ra 02" << endl;

	co_return 100;
}

cotask_return<int> cotask_func_rb()
{
	cout << "cotask_func_rb 01" << endl;
	co_await std::suspend_always();
	cout << "cotask_func_rb 02" << endl;

	co_return 200;
}


int main(int argc, char* argv[])
{
	auto cotask0 = cotask_func_ra();
	auto cotask1 = cotask_func_rb();

	while (!cotask0.done() || !cotask1.done())
	{
		if (!cotask0.done())
		{
			cotask0();
		}

		if (!cotask1.done())
		{
			cotask1();
		}
	}

	cout << cotask0.return_value() << endl;
	cout << cotask1.return_value() << endl;


	return 0;
}

실행 결과는 아래와 같습니다.

cotask_func_ra 01
cotask_func_rb 01
cotask_func_ra 02
cotask_func_rb 02
100
200


cotask_return

C++ 코루틴(coroutine) 활용 강좌: #2 : co_await의 예제와는 다르게 cotask_return 클래스를 정의하였습니다. 해당 클래스는 promise_type에 co_return관련 정의가 있고 처리를 하고 있습니다. 이전 예제에서 설명했던 cotask_noreturn와 틀린 점은 co_return으로 값을 리턴하기 때문에 리턴되는 값을 처리하는 부분이 있다는 점입니다. 코루틴 관련 상태 객체는 이렇게 코루틴 함수의 형태에 따라 정의하거나 처리하는 함수의 형태가 틀려지게 됩니다. 만약 처리하는 형태에 맞는 인터페이스가 구현되어 있지 않은 경우 컴파일러에서 에러가 발생합니다.


co_return

코루틴 함수는 return을 사용할 수 없습니다. co_return으로 값을 리턴해야 합니다. 당연한 이야기겠지만 co_return은 값을 리턴한 뒤 코루틴 함수를 종료합니다.

 

반응형