Weston Inside - 基礎數據結構詳解

Weston

Weston是Wayland compositor的參考實現,廣泛應用與AGL和GENIVI 車機Linux系統,各個版本的weston代碼可以在 https://github.com/wayland-project/weston 找到,架構設計分析可以參考文章 https://blog.csdn.net/fyh2003/article/details/49253713,本文旨在分析它的核心數據結構,幫助理解和看懂它的源代碼

 

核心數據結構

Wayland 核心數據結構

 

#ifdef __GNUC__
#define wl_container_of(ptr, sample, member)                            \
        (__typeof__(sample))((char *)(ptr)      -                       \
                 ((char *)&(sample)->member - (char *)(sample)))
#else
#define wl_container_of(ptr, sample, member)                            \
        (void *)((char *)(ptr)  -                                       \
                 ((char *)&(sample)->member - (char *)(sample)))
#endif

#define wl_list_for_each(pos, head, member)                             \
        for (pos = 0, pos = wl_container_of((head)->next, pos, member); \
             &pos->member != (head);                                    \
             pos = wl_container_of(pos->member.next, pos, member))

#define wl_list_for_each_safe(pos, tmp, head, member)                   \
        for (pos = 0, tmp = 0,                                          \
             pos = wl_container_of((head)->next, pos, member),          \
             tmp = wl_container_of((pos)->member.next, tmp, member);    \
             &pos->member != (head);                                    \
             pos = tmp,                                                 \
             tmp = wl_container_of(pos->member.next, tmp, member))
wl_container_of 示意圖

如上圖所示,wl_container_of的作用是根據ptr指針找出包含它的父結構的指針

 

wl_list_for_each

 

有了wl_container_of的基礎就很容易理解wl_list_for_each的實現了,通過head->next指針找到它的父結構指針pos,然後通過pos->member->next指針循環遍歷整個list上的__typeof__(pos)數據結構實例;wl_list_for_each_safe通過增加一個tmp指針防止越界作爲wl_list_for_each的safe版本實現

 

WL_EXPORT void
wl_list_init(struct wl_list *list)
{
        list->prev = list;
        list->next = list;
}

WL_EXPORT void
wl_list_insert(struct wl_list *list, struct wl_list *elm)
{
        elm->prev = list;
        elm->next = list->next;
        list->next = elm;
        elm->next->prev = elm;
}

WL_EXPORT void
wl_list_remove(struct wl_list *elm)
{
        elm->prev->next = elm->next;
        elm->next->prev = elm->prev;
        elm->next = NULL;
        elm->prev = NULL;
}

wl_list_init wl_list_insert wl_list_remove 是對wl_list做雙向鏈表的操作,大學C語音數據結構的基礎內容

static inline void
wl_signal_add(struct wl_signal *signal, struct wl_listener *listener)
{
        wl_list_insert(signal->listener_list.prev, &listener->link);
}

static inline struct wl_listener *
wl_signal_get(struct wl_signal *signal, void *notify)
{
        struct wl_listener *l;

        wl_list_for_each(l, &signal->listener_list, link)
                if (l->notify == notify)
                        return l;

        return NULL;
}

static inline void
wl_signal_emit(struct wl_signal *signal, void *data)
{
        struct wl_listener *l, *next;

        wl_list_for_each_safe(l, next, &signal->listener_list, link)
                l->notify(l, data);
}

 

wl_signal list

wl_signal通過成員listener_list形成鏈表,wl_signal_emit通過wl_list_for_each_safe遍歷整個鏈表中的wl_listener數據結構,調用註冊到wl_signal上的notify函數

 

wl_event_loop_add 流程圖

 

wl_event_loop是weston的核心事件循環loop結構,wl_event_source是加入該loop等待weston處理的事件可以再細分爲wl_event_source_fd wl_event_source_timer wl_event_source_signal 等事件,上圖展示瞭如果將wl_event_source_xxx 事件加入事件循環loop的代碼流程

 

wl_display_run 消息循環

 

weston主線程就是一個不斷從Loop中獲取event事件進行處理的循環,上圖解釋了該循環的代碼流程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章