Как использовать список из sys/queue.h?
В настоящее время я реализовал один и тот же список, например:
struct PeerNode {
struct Peer* cargo;
struct PeerNode* next;
};
... и у меня есть структура, которая содержит пару этих связанных списков, например:
struct Torrent {
...
struct PeerNode* peer_list;
struct PeerNode* unchoked_peers;
...
}
Я хотел бы заменить это, используя макросы, предоставленные sys/queue.h
. Я понимаю, что я мог бы заменить свой код на что-то вроде этого:
struct Torrent {
...
LIST_ENTRY(PeerNode, Peer) peer_list;
struct PeerNode* unchoked_peers;
...
}
Затем, посмотрев man queue
, я считаю, что инициализирую списки, выполнив что-то вроде этого:
LIST_INIT(&peer_list);
LIST_INIT(unchoked_peers);
Однако я не понимаю, как факторы LIST_ENTRY
влияют на использование списка. На странице man
говорится: "Макрос LIST_ENTRY
объявляет структуру, которая соединяет элементы в списке", но я действительно не понимаю, что это значит.
Почему я хочу объявить структуру для подключения элементов в списке? Должен ли каждый node подключаться к следующему node с помощью указателя, как и моя первоначальная реализация списка ссылок? Как заменить мои связанные списки на реализацию, предоставленную sys/queue.h
? Как бы вставить элемент в список?
Ответы
Ответ 1
LIST_ENTRY создает поля для размещения в вашей структуре, которые подходят для связывания элементов, поэтому вам не нужно заботиться о специфике этих указателей.
struct foo {
int a, b, c;
/* This is instead of "struct foo *next" */
LIST_ENTRY(foo) pointers;
};
Чтобы затем создать список, вы должны использовать LIST_HEAD():
struct Torrent {
LIST_HEAD(foo_list, foo) bar;
};
Вы можете инициализировать заголовок списка, используя LIST_INIT():
struct Torrent t;
LIST_INIT(&t.bar);
Вы можете вставить элементы, используя макросы LIST_INSERT _ *():
struct foo *item = malloc(sizeof(struct foo));
LIST_INSERT_HEAD(&t.bar, item, pointers);
Все это было взято из списка примеров на страницах руководства по адресу http://www.manpagez.com/man/3/queue/