2012-03-12 5 views
4

Я создал следующую очередь приоритета в C++Priority Queue 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(), независимо от того он должен вернуть объект потока с наименьшим приоритетом. Здесь есть проблемы?

+2

Можете ли вы показать код, в котором вы поместили записи в очередь? –

+0

Привет, я обновил код. Здесь вы можете увидеть, как я нажал элементы. @ JoachimPileborg –

+0

вы отправили * лот * кода, * most * из этого не имеет значения. –

ответ

3

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

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

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

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

+0

Извините, я не понимаю. Вы можете уточнить: «Похоже, вы передаете указатель на тот же кусок памяти в очередь»? –

+0

привет, я обновил код. –

+0

, вы можете проверить это, выскочив из очереди и проверив извлеченные элементы. –

1

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

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

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

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

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

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

Я предлагаю идти с альтернативной 2.

+0

Сначала я не использовал указатель в объекте только для очереди. Тогда это давало мне значение для мусора, когда я пытался распечатать содержимое очереди. Теперь все в порядке, только внутреннее сравнение не работает. –

+0

@Pbasak Поверьте мне, используя указатели на локальные переменные, рано или поздно программа взорвется в вашем лице (образно говоря). Я предполагаю, что каждый вызов 'ThreadController :: thread_register' чистой удачи заставляет структуру занимать ту же самую область памяти, что означает, что она« перезапишет »старые данные. –

+0

Да, я понял проблему. В каждом push-вызове одни и те же данные перезаписываются. SO, одни и те же объекты информации потока многократно выдвигаются. –

Смежные вопросы