77 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#pragma once
 | 
						|
 | 
						|
namespace ts::server::file {
 | 
						|
    enum struct ExecuteStatus {
 | 
						|
        UNKNOWN,
 | 
						|
        WAITING,
 | 
						|
        SUCCESS,
 | 
						|
        ERROR
 | 
						|
    };
 | 
						|
 | 
						|
    template<typename VariantType, typename T, std::size_t index = 0>
 | 
						|
    constexpr std::size_t variant_index() {
 | 
						|
        if constexpr (index == std::variant_size_v<VariantType>) {
 | 
						|
            return index;
 | 
						|
        } else if constexpr (std::is_same_v<std::variant_alternative_t<index, VariantType>, T>) {
 | 
						|
            return index;
 | 
						|
        } else {
 | 
						|
            return variant_index<VariantType, T, index + 1>();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    struct EmptyExecuteResponse { };
 | 
						|
    template <class error_t, class response_t = EmptyExecuteResponse>
 | 
						|
    class ExecuteResponse {
 | 
						|
            typedef std::variant<EmptyExecuteResponse, error_t, response_t> variant_t;
 | 
						|
        public:
 | 
						|
            ExecuteStatus status{ExecuteStatus::WAITING};
 | 
						|
 | 
						|
            [[nodiscard]] inline auto response() const -> const response_t& { return std::get<response_t>(this->response_); }
 | 
						|
 | 
						|
            template <typename = std::enable_if_t<!std::is_void<error_t>::value>>
 | 
						|
            [[nodiscard]] inline const error_t& error() const { return std::get<error_t>(this->response_); }
 | 
						|
 | 
						|
            inline void wait() const {
 | 
						|
                std::unique_lock nlock{this->notify_mutex};
 | 
						|
                this->notify_cv.wait(nlock, [&]{ return this->status != ExecuteStatus::WAITING; });
 | 
						|
            }
 | 
						|
 | 
						|
            template<typename _Rep, typename _Period>
 | 
						|
            [[nodiscard]] inline bool wait_for(const std::chrono::duration<_Rep, _Period>& time) const {
 | 
						|
                std::unique_lock nlock{this->notify_mutex};
 | 
						|
                return this->notify_cv.wait_for(nlock, time, [&]{ return this->status != ExecuteStatus::WAITING; });
 | 
						|
            }
 | 
						|
 | 
						|
            template <typename... Args>
 | 
						|
            inline void emplace_success(Args&&... args) {
 | 
						|
                constexpr auto success_index = variant_index<variant_t, response_t>();
 | 
						|
 | 
						|
                std::lock_guard rlock{this->notify_mutex};
 | 
						|
                this->response_.template emplace<success_index, Args...>(std::forward<Args>(args)...);
 | 
						|
                this->status = ExecuteStatus::SUCCESS;
 | 
						|
                this->notify_cv.notify_all();
 | 
						|
            }
 | 
						|
 | 
						|
            template <typename... Args>
 | 
						|
            inline void emplace_fail(Args&&... args) {
 | 
						|
                constexpr auto error_index = variant_index<variant_t, error_t>();
 | 
						|
 | 
						|
                std::lock_guard rlock{this->notify_mutex};
 | 
						|
                this->response_.template emplace<error_index, Args...>(std::forward<Args>(args)...);
 | 
						|
                this->status = ExecuteStatus::ERROR;
 | 
						|
                this->notify_cv.notify_all();
 | 
						|
            }
 | 
						|
 | 
						|
            [[nodiscard]] inline bool succeeded() const {
 | 
						|
                return this->status == ExecuteStatus::SUCCESS;
 | 
						|
            }
 | 
						|
 | 
						|
            ExecuteResponse(std::mutex& notify_mutex, std::condition_variable& notify_cv)
 | 
						|
                    : notify_mutex{notify_mutex}, notify_cv{notify_cv} {}
 | 
						|
        private:
 | 
						|
            variant_t response_{}; /* void* as default value so we don't initialize error_t or response_t */
 | 
						|
 | 
						|
            std::mutex& notify_mutex;
 | 
						|
            std::condition_variable& notify_cv;
 | 
						|
    };
 | 
						|
} |