#ifndef MYQUEUE_H_
#define MYQUEUE_H_
#include <iostream>
#include <queue>
#include <list>
#include <mutex>
#include <condition_variable>

namespace ai_matrix
{
    template <typename T>
    class MyQueue final
    {
    public:
        MyQueue(int max = 32) : max_size_(max), is_stoped_(false) {}
        MyQueue(const MyQueue &) = delete;
        MyQueue(MyQueue &&) = delete;
        MyQueue &operator=(const MyQueue &) = delete;
        MyQueue &operator=(MyQueue &&) = delete;
        ~MyQueue() = default;

        int push(const T &value, bool isWait = false)
        {
            std::unique_lock<std::mutex> lk(mutex_);
			
            while (queue_.size() >= max_size_ && isWait && !is_stoped_)
            {
                printf("myqueue full");
                cond_not_full_.wait(lk);
            }
			
            if (is_stoped_)
            {
                return 1;
            }
			
            if (queue_.size() >= max_size_)
            {
                return 2;
            }
			
            queue_.push(value);
			
            cond_not_empty_.notify_one();
			
            return 0;
        }

        int pop(T &value, bool isWait = false)
        {
            std::unique_lock<std::mutex> lk(mutex_);

            while (queue_.empty() && isWait && !is_stoped_)
            {
                cond_not_empty_.wait(lk);
            }

            if (is_stoped_)
            {
                return 1;
            }

            if (queue_.empty())
            {
                return 2;
            }

            value = queue_.front();
            queue_.pop();

            cond_not_full_.notify_one();

            return 0;
        }

        void stop()
        {
            {
                std::unique_lock<std::mutex> lk(mutex_);
                is_stoped_ = true;
            }

            cond_not_full_.notify_all();
            cond_not_empty_.notify_all();
        }

		int getSize() 
		{
			return queue_.size();
		}

        void setMaxSize(int iMaxSize)
        {
            max_size_ = iMaxSize;
        }

    private:
        std::queue<T> queue_; //队列

        std::condition_variable cond_not_empty_;
        std::condition_variable cond_not_full_;

        std::mutex mutex_;

        int max_size_;

        bool is_stoped_;
    };
}

#endif