0

我正在编写一个带有双链表的简单计时器。如果我将链表头定义如下,它将起作用。

struct timer_head
{
    struct timer* prev;
    struct timer* next;
    pthread_spinlock_t lock;
};

但是如果我将头部定义如下,那么插入就会失败,每次插入后我都会丢失前一个节点。

struct timer_head
{
    struct timer* next;
    struct timer* prev;

    pthread_spinlock_t lock;
};

我的部分代码:

struct timer
{
    struct timer* prev;
    struct timer* next;
    struct timespec start;
    struct timespec interval;
    void* par, *par2; 
    /*if handle return 0    */
    /*then delete this timer    */
    /*else restart it       */
    int (*handler) (void* par);
};

struct timer_head
{
    struct timer* prev;
    struct timer* next;
/*
*if i changed the previous definition to 
*code below, then my list insertion will failed
*why?
*/
/*  struct timer* next;
    struct timer* prev;
*/
    pthread_spinlock_t lock;
};
void timer_queue_init(struct timer_head* lst)
{
    pthread_spin_init(&lst->lock, PTHREAD_PROCESS_SHARED);
    lst->next = lst->prev = (struct timer*)lst;
}

static void print_queue(struct timer_head* lst)
{
    pthread_spin_lock(&(lst->lock));
    struct timer* fst = lst->next;

    printf("list travserse:\t");
    while (fst != (struct timer*) lst)
    {
    printf("inteval : %ld, ", fst->interval.tv_nsec);
    fst = fst->next;
    }
    printf("\n");
    pthread_spin_unlock(&(lst->lock));
}


void timer_queue_insert(struct timer_head* lst, struct timer* nt)
{
    pthread_spin_lock(&(lst->lock));
    struct timer* ptr = lst->next;

    /*insert into list, sorted as earlist execute time  */
    while (ptr != (struct timer*) lst &&
        timespec_cmp(&(ptr->start), &(ptr->interval),
        &(nt->start), &(nt->interval)) <= 0)
    {
    printf("next\n");
    ptr = ptr->next;
    }
    nt->next = ptr;
    nt->prev = ptr->prev;

    nt->prev->next = nt;
    ptr->prev = nt;



    /* send signal to manage thread */
    if (!qlen)
    {
    printf("start :%ld s, %ld ns ", nt->start.tv_sec, nt->start.tv_nsec);
    printf("interval :%lds, %ld ns\n", nt->interval.tv_sec, nt->interval.tv_nsec);
    pthread_cond_signal(&wait);
    }
    ++qlen;
    pthread_spin_unlock(&(lst->lock));

    printf("traver after insert\t");
    print_queue(lst);
}
4

2 回答 2

2

此代码将指向 a 的指针转换为指向 astruct timer_head的指针struct timer

void timer_queue_init(struct timer_head* lst)
{
   pthread_spin_init(&lst->lock, PTHREAD_PROCESS_SHARED);
   lst->next = lst->prev = (struct timer*)lst; /* HERE */
}

只要它们具有相同的结构,这(幸运)就可以工作。你struct timer看起来像这样:

struct timer
{
  struct timer* prev;
  struct timer* next;
  ...

因此,放在prevbeforenext允许演员“碰巧”保留 and 的值prevnext尽管您绝对不应该这样做。“碰巧”工作的代码的问题是有时它会碰巧不起作用。

于 2013-04-04T06:13:31.950 回答
1

查看您的代码,问题在于您将 atimer_head *转换为timer *. 如果timer_head看起来像

struct {
  struct timer * next;
  struct timer * prev;
  ...
}

然后在内存中你(可能)有以下布局

[next][prev]

. 如果同时timer看起来像

struct {
  struct timer * prev;
  struct timer * next;
  ...
}

,就像在您的代码中一样,它在内存中具有不同的布局,即类似于

[prev][next]

. 你从一个指针到另一个指针的转换会改变 prev 和 next 的含义。(在一种情况下是内存中的第一个和第二个指针,在另一种情况下是内存中的第二个和第一个指针)。

于 2013-04-04T06:18:56.670 回答