我正在编写一个带有双链表的简单计时器。如果我将链表头定义如下,它将起作用。
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);
}
答案 0 :(得分:2)
此代码将指向struct 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;
...
因此,在prev
之前放置next
可以让演员“碰巧”保留prev
和next
的值,但绝对不应该这样做。代码“碰巧”工作的问题是,有时它会发生不起作用。
答案 1 :(得分:1)
查看您的代码,问题是您将timer_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的立场。 (在一种情况下,内存中的第一个和第二个指针,在另一种情况下是内存中的第二个和第一个指针)。