Run Code  | API  | Code Wall  | Misc  | Feedback  | Login  | Theme  | Privacy  | Patreon 

MSVC14 <experimental/generator> header

Language: Layout:
+ ] Compiler args + ] Show input
Compilation time: 2,56 sec, absolute running time: 0,22 sec, absolute service time: 2,8 sec 
edit mode |  history  | discussion
/***
*generator
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*       Purpose: Library support of coroutines. generator class
*       http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0057r0.pdf
*
*       [Public]
*
****/
#pragma once
#ifndef _EXPERIMENTAL_GENERATOR_
#define _EXPERIMENTAL_GENERATOR_
#ifndef RC_INVOKED

#ifndef _RESUMABLE_FUNCTIONS_SUPPORTED
 #error <experimental/generator> requires /await compiler option
#endif /* _RESUMABLE_FUNCTIONS_SUPPORTED */

#include <experimental/resumable>

#pragma pack(push,_CRT_PACKING)
#pragma push_macro("new")
#undef new

_STD_BEGIN

namespace experimental {

	template <typename _Ty, typename _Alloc = allocator<char> >
	struct generator
	{
		struct promise_type
		{
			_Ty const * _CurrentValue;

			promise_type& get_return_object()
			{
				return *this;
			}

			bool initial_suspend()
			{
				return (true);
			}

			bool final_suspend()
			{
				return (true);
			}

			void yield_value(_Ty const & _Value)
			{
				_CurrentValue = _STD addressof(_Value);
			}

			using _Alloc_traits = allocator_traits<_Alloc>;
			using _Alloc_of_char_type = typename _Alloc_traits::template rebind_alloc<char>;

			void* operator new(size_t _Size)
			{
				_Alloc_of_char_type _Al;
				return _Al.allocate(_Size);
			}

			void operator delete(void* _Ptr, size_t _Size) _NOEXCEPT
			{
				_Alloc_of_char_type _Al;
				return _Al.deallocate(static_cast<char*>(_Ptr), _Size);
			}
		};

		struct iterator
			: _STD iterator<input_iterator_tag, _Ty>
		{
			coroutine_handle<promise_type> _Coro;

			iterator(nullptr_t)
				: _Coro(nullptr)
			{
			}

			iterator(coroutine_handle<promise_type> _CoroArg)
				: _Coro(_CoroArg)
			{
			}

			iterator& operator++()
			{
				_Coro.resume();
				if (_Coro.done())
					_Coro = nullptr;
				return *this;
			}

			iterator operator++(int) = delete;
			// generator iterator current_value
			// is a reference to a temporary on the coroutine frame
			// implementing postincrement will require storing a copy
			// of the value in the iterator.
			//{
			//	auto _Result = *this;
			//	++(*this);
			//	return _Result;
			//}

			bool operator==(iterator const& _Right) const
			{
				return _Coro == _Right._Coro;
			}

			bool operator!=(iterator const& _Right) const
			{
				return !(*this == _Right);
			}

			_Ty const& operator*() const
			{
				return *_Coro.promise()._CurrentValue;
			}

			_Ty const* operator->() const
			{
				return _STD addressof(operator*());
			}

		};

		iterator begin()
		{
			if (_Coro)
			{
				_Coro.resume();
				if (_Coro.done())
					return {nullptr};
			}

			return {_Coro};
		}

		iterator end()
		{
			return {nullptr};
		}

		explicit generator(promise_type& _Prom)
			: _Coro(coroutine_handle<promise_type>::from_promise(_STD addressof(_Prom)))
		{
		}

		generator() = default;

		generator(generator const&) = delete;

		generator& operator = (generator const&) = delete;

		generator(generator && _Right)
			: _Coro(_Right._Coro)
		{
			_Right._Coro = nullptr;
		}

		generator& operator = (generator && _Right)
		{
			if (&_Right != this)
			{
				_Coro = _Right._Coro;
				_Right._Coro = nullptr;
			}
		}

		~generator()
		{
			if (_Coro)
			{
				_Coro.destroy();
			}
		}
	private:
		coroutine_handle<promise_type> _Coro = nullptr;
	};

} // namespace experimental

_STD_END

#pragma pop_macro("new")
#pragma pack(pop)
#endif /* RC_INVOKED */
#endif /* _EXPERIMENTAL_GENERATOR_ */

    
                
λ
.NET NoSQL database for rapid development