Приоритетная очередь C ++

Я создал следующую очередь приоритетов на C ++

priority_queue < ThreadInfo*, vector<ThreadInfo*>, CompareThread > thread_queue;

где класс ThreadInfo

class ThreadInfo {
public:
    ThreadInfo();
    ThreadInfo(const ThreadInfo& orig);
    ThreadInfo(int thread_id,int init_time,int sleep_time,int run_time,int priority,int is_critical)
    {
        this->thread_id=thread_id;
        this->is_critical=is_critical;
        this->init_time=init_time;
        this->priority=priority;
        this->run_time=run_time;
        this->sleep_time=sleep_time;
    }

    void set_critical(bool value)
    {
        is_critical=value;
    }
    bool get_critical()
    {
        return is_critical;
    }
    void set_sleep_time(long value)
    {
        sleep_time=value;
    }

    long get_sleep_time(long value)
    {
        return sleep_time;
    }

    void set_run_time(long value)
    {
        sleep_time=value;
    }

    long get_run_time(long value)
    {
        return sleep_time;
    }
    int get_lock_type()
    {
        return lock_type;
    }
    void set_lock_type(int lock_type)
    {
        this->lock_type=lock_type;
    }

    int get_priority()
    {
        return priority;
    }
    void set_priority(int value)
    {
        this->priority=value;
    }

    unsigned long int get_thread_id()
    {
        return thread_id;
    }
    void set_thread_id(unsigned long int value)
    {
        this->thread_id=value;
    }
    virtual ~ThreadInfo();

private:
    unsigned long int thread_id;
    long init_time;
    long sleep_time;
    long run_time;
    int priority;
    bool is_critical;
    //1=spin,2=busy,3=semaphore
    int lock_type;



};

и класс сравнения

class CompareThread {
public:
    bool operator()(ThreadInfo* th1, ThreadInfo* th2)
    {
       if (th1->get_priority()>th2->get_priority()) return true;

       return false;
    }
};

затем я вставляю элемент в следующую функцию,

void ThreadScheduler::register_thread(ThreadInfo &th)
{

        thread_queue.push(&th);


}

Я вызываю регистр потока из следующей функции,

int ThreadController::thread_register(pthread_t &t, int priority, bool critical)
{
    ThreadInfo ti;
    cout<<"t reg:"<<t<<endl;
    ti.set_thread_id(t);
    ti.set_critical(critical);
    ti.set_priority(priority);
    ThreadScheduler::Instance()->register_thread(ti);
}

но каждый раз, когда я помещаю какой-либо объект threadinfo в очередь, я получаю самый последний объект при вызове thread_queue.top (), должен ли он возвращать объект потока с самым низким приоритетом. Здесь какие-то проблемы?


person P basak    schedule 12.03.2012    source источник
comment
Можете показать код, где ставите записи в очередь?   -  person Some programmer dude    schedule 12.03.2012
comment
Привет, я обновил код. Здесь вы можете увидеть, как я вставлял элементы. @ JoachimPileborg   -  person P basak    schedule 12.03.2012
comment
вы опубликовали много кода, большая часть не имеет отношения к делу ..   -  person Karoly Horvath    schedule 12.03.2012
comment
вы можете показать код, в котором вы вызываете register_thread?   -  person perreal    schedule 12.03.2012
comment
хорошо .. теперь покажите нам, где вы создаете эти ThreadInfo-ы   -  person Karoly Horvath    schedule 12.03.2012
comment
есть ли причина, по которой вы не слишком используете std::priority_queue<>?   -  person Johann Gerell    schedule 12.03.2012
comment
привет, я использую очередь приоритета std.   -  person P basak    schedule 12.03.2012
comment
Привет, содержимое очереди в порядке, но, думаю, сравнение по какой-то причине не работает. потому что самый нижний элемент не находится сверху.   -  person P basak    schedule 12.03.2012


Ответы (2)


Вы передаете в очередь указатель на тот же фрагмент памяти. Вы вызываете register_thread со ссылкой на локальный объект и ставите его адрес в очередь. Вот почему они все одинаковы. Другая проблема заключается в том, что когда вы покидаете функцию thread_register, локальный ti будет удален (вне области видимости), и у вас не будет действительных записей в очереди.

Что вам нужно сделать, так это выделить новую память для каждой информации и скопировать данные в эту память. Таким образом, каждый указатель элемента, который вы вставляете в очередь, должен исходить от другого new, если у вас есть конструктор копирования, это будет делать:

void ThreadScheduler::register_thread(ThreadInfo &th)
{
        thread_queue.push(new ThreadInfo(th));
        /* ... */
}

проверьте это: https://stackoverflow.com/a/986093/390913

person perreal    schedule 12.03.2012
comment
Извините, я не понимаю. Можете ли вы уточнить. Похоже, вы передаете указатель на тот же фрагмент памяти в очередь? - person P basak; 12.03.2012
comment
вы можете проверить это, выйдя из очереди и проверив выбранные элементы. - person Karoly Horvath; 12.03.2012
comment
привет, я нажимаю здесь ссылку на объект threadinfo, мне все еще нужен конструктор копирования? - person P basak; 12.03.2012
comment
@Pbasak, глядя на ваш класс, вам не нужен конструктор, на самом деле подойдет конструктор по умолчанию. Не забудьте удалить новые объекты, когда закончите. - person perreal; 12.03.2012
comment
Привет, содержимое очереди в порядке, но, думаю, сравнение по какой-то причине не работает. потому что самый нижний элемент не находится сверху. - person P basak; 12.03.2012
comment
напишите < operator для вашей информации о задачах, в которой вы сравниваете их по приоритету. см. ссылку в посте. - person perreal; 12.03.2012

Проблема в том, что вы используете указатель на переменную, объявленную локально в функции. Как только функция (ThreadController::thread_register) завершена, локальная переменная больше не существует, и теперь указатель указывает на нераспределенную память.

Для этого есть два решения:

  1. Используйте умные указатели, например std::shared_ptr, и создайте новый указатель в ThreadController::thread_register:

    std::shared_ptr<ThreadInfo> ti(new ThreadInfo);
    

    Конечно, вы должны не забыть перейти на std::shared_ptr и везде и использовать оператор доступа -> вместо ..

  2. Не используйте указатели вообще и позвольте копировать данные класса (которые довольно минимальны и просты).

Я предлагаю выбрать вариант 2.

person Some programmer dude    schedule 12.03.2012
comment
Сначала я не использовал указатель в очереди только для объекта потока. Затем он давал мне значение мусора, когда я пытался распечатать содержимое очереди. Теперь все в порядке, просто внутреннее сравнение не работает. - person P basak; 12.03.2012
comment
@Pbasak Поверьте, использование указателей на локальные переменные рано или поздно заставит программу взорваться (образно говоря). Я предполагаю, что каждый вызов ThreadController::thread_register по чистой случайности заставляет структуру занимать точно такую ​​же область памяти, а это означает, что старые данные будут перезаписаны. - person Some programmer dude; 12.03.2012
comment
да, я разобрался с проблемой. При каждом push-вызове одни и те же данные перезаписываются. Итак, одни и те же информационные объекты потока помещаются несколько раз. - person P basak; 12.03.2012