view TaskManager/kernel/ppe/QueueInfo.h @ 962:9f9b2bbc9a10

QueueInfo fix
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 05 Aug 2010 08:48:57 +0900
parents 02f1a707ee82
children
line wrap: on
line source

#ifndef INCLUDED_QUEUE_INFO
#define INCLUDED_QUEUE_INFO

#include "base.h"
#include "types.h"

#if 0
template <typename T> class Queue : T {
public:

    T();

    T *waiter;
    T *next;
    T *prev;

    void initOnce();  // to initialize object in pool
    void freeOnce();  // to destroy object in pool

    // virual void init();
};
#endif

template <typename T> class QueueInfo : public T {

public:
    /* constructor */

    /** 
	singleton queuePool constructor 
	Do not use this as a Queue
    */
    QueueInfo<T>(){
	queueInfoInit();
    }
    /** 
	normal constructor requires
    */
    QueueInfo<T>(QueueInfo<T> *p) {
	queueInfoInit();
	queuePool = p;
    }

    BASE_NEW_DELETE(QueueInfo);

    /* functions */
    T *create();

    void free_(T *queue);

    void addFirst(T* e);
    void addLast(T* e);
    T* getFirst();
    T* getLast();
    int remove(T* e);
    T* poll();
    void moveToFirst(T* e); // or use();
    T* get(int index);
    T* find(T *task);
    int empty();
    void freePool() ;
    void freeAll();

    // Iterator
    T* getNext(T* q) ;
    int length();

private:
    /* variables */

    /* we cannot use static in template */
    /* static */ QueueInfo<T> *queuePool;
    T* first;
    T* last;

    /* functions */
    int extend_pool(int num);
    void destroy();  
    void queueInfoInit();
}  ;



#ifdef CHECK
#include <stdio.h>
#endif
#include <stdlib.h>


/** 
    Use singleton queuePool constructor 
    all queueInfo should share this as a pool.

    exteren QueueInfo<H> pool;
    QueueInfo<H> pool = new QueueInfo<H>();

    use this in non initialize envrionment is wrong.
*/

template<typename T>void QueueInfo<T>::queueInfoInit() {
    // 最初の一つは自分
    first = last = this;
    this->next = this->prev = this;
    this->waiter = NULL;
}

template<typename T>void
QueueInfo<T>::freePool() { 
    for(T * p = queuePool->waiter; p; ) {
	T * next = p->waiter;
	p->waiter = NULL;
	p->freeOnce();
	free(p);
	p = next;
    }
}

/**
    all pools are shared among QueueInfo (separated by size and type).
    it automatically extended by 64.
 */
template<typename T>int
QueueInfo<T>::extend_pool(int num)
{
#ifdef CHECK
    if (queuePool) fprintf(stderr, "don't use queuePool directly");
#endif

    T* q = (T*)malloc(sizeof(T)*(num+1)+DEFAULT_ALIGNMENT);

    // First Queue is previous pool
    q->waiter = this->waiter; this->waiter = q;
    q = (T*)ROUND_UP_ALIGN((long)q, DEFAULT_ALIGNMENT);
    q++;

    /* Connect all free queue in the pool */
    T* p = q;
    for (; num-- > 0;) {
        p->waiter = NULL;
	p->initOnce();
        addLast(p);
	p = (T*)ROUND_UP_ALIGN((long)(p+1),DEFAULT_ALIGNMENT);
    }

    return 0;

}

/**
 * Task をプールから取って来て返す
 *
 * @param [cmd] タスクコマンド
 */
template<typename T>T *
QueueInfo<T>::create()
{
    T * q =  queuePool->poll();
    if (! q)  {
	queuePool->extend_pool(64);
	q = queuePool->poll();
    }
    q->init();
    return q;
}


template<typename T>void
QueueInfo<T>::free_(T * q)
{
    q->waiter = NULL;
    queuePool->addLast(q);
}


/*!
  QueueInfo<T> は空にならない。最低1個は要素が入っていて
  1個目は特別扱いする。getFirst すると first->next を返す
 */

/*!
  最初の1個は特別扱いなので、それの後に追加していく
 */
template<typename T>void
QueueInfo<T>::addFirst(T* e)
{
    e->prev = first;
    e->next = first->next;
    first->next->prev = e;
    first->next = e;
}

template<typename T>void
QueueInfo<T>::addLast(T* e)
{
#ifdef CHECK
    if (find(e)) { 
	fprintf(stderr,"Add duplicate task %0x\n",(int)e);
	return; 
       // ...  
    }
#endif
    e->next = first;
    e->prev = last;
    last->next = e;
    last = e;
}

template<typename T>T*
QueueInfo<T>::getFirst()
{
    if (empty()) return NULL;
    return first->next;
}

template<typename T>T*
QueueInfo<T>::getLast()
{
    if (empty()) return NULL;
    return last;
}

template<typename T>int
QueueInfo<T>::remove(T* e)
{
#ifdef CHECK
    if (!find(e)) { 
	fprintf(stderr,"Remove non existing task %0x\n",(int)e);
	return 0; 
       // ...  
    }
#endif
    e->prev->next = e->next;
    e->next->prev = e->prev;

    if (first->next == e) {
	first->next = e->next;
    }
    if (last == e) {
	last = e->prev;
    }

    e->prev = NULL;
    e->next = NULL;

    return 1;
}

/*!
  リストの先頭を取得および削除する。リストが空の場合は NULL を返す。
 */

template<typename T>T*
QueueInfo<T>::poll()
{
    T* e = first->next;
    if (e == this) {
	return NULL;
    }
    remove(e);
    return e;
}

template<typename T>void
QueueInfo<T>::moveToFirst(T* e)
{
    remove(e);
    addFirst(e);
}

/*!
  リスト内の指定された位置にある要素を返す。
  要素数を超えた位置を指定した場合 NULL を返す。
 */

template<typename T>T*
QueueInfo<T>::get(int index)
{
    T* e = first->next;
    for (int i = 0; i < index; i++) {
	if (e->next == this) return NULL;
	e = e->next;
    }
    return e;
}

template<typename T>T*
QueueInfo<T>::find(T* task)
{
    T* e = first->next;
    for(;;) {
	if (e == this) return NULL;
	if (e == task) break;
	e = e->next;
    }
    return e;
}

template<typename T>int
QueueInfo<T>::empty()
{
    return this->next == this;
}

template<typename T>T*
QueueInfo<T>::getNext(T* q) 
{
    if (q->next==this) return NULL;
    return q->next;
}

template<typename T>int
QueueInfo<T>::length() 
{
    int i = 0;
    if (empty()) return 0;
    T* e = first;
    while((e = e->next) != this ) i++;
    return i;
}

template<typename T>void
QueueInfo<T>::freeAll()
{
    T* t;
    while((t=poll())) free_(t);
}



/* end */



#endif