Blender V4.3
wm_message_bus.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstring>
10
11#include "CLG_log.h"
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_listbase.h"
16#include "BLI_utildefines.h"
17
18#include "BLI_ghash.h"
19
20#include "WM_types.hh"
21
24
25/* -------------------------------------------------------------------------- */
30
31using wmMsgTypeInitFn = void (*)(wmMsgTypeInfo *);
32
37
39{
40 for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
42 }
43}
44
46{
47 wmMsgBus *mbus = static_cast<wmMsgBus *>(MEM_callocN(sizeof(*mbus), __func__));
48 const uint gset_reserve = 512;
49 for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
50 wmMsgTypeInfo *info = &wm_msg_types[i];
52 info->gset.hash_fn, info->gset.cmp_fn, __func__, gset_reserve);
53 }
54 return mbus;
55}
56
58{
59 for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
60 wmMsgTypeInfo *info = &wm_msg_types[i];
62 }
63 MEM_freeN(mbus);
64}
65
66void WM_msgbus_clear_by_owner(wmMsgBus *mbus, void *owner)
67{
68 wmMsgSubscribeKey *msg_key, *msg_key_next;
69 for (msg_key = static_cast<wmMsgSubscribeKey *>(mbus->messages.first); msg_key;
70 msg_key = msg_key_next)
71 {
72 msg_key_next = msg_key->next;
73
74 wmMsgSubscribeValueLink *msg_lnk_next;
75 for (wmMsgSubscribeValueLink *msg_lnk =
76 static_cast<wmMsgSubscribeValueLink *>(msg_key->values.first);
77 msg_lnk;
78 msg_lnk = msg_lnk_next)
79 {
80 msg_lnk_next = msg_lnk->next;
81 if (msg_lnk->params.owner == owner) {
82 if (msg_lnk->params.tag) {
83 mbus->messages_tag_count -= 1;
84 }
85 if (msg_lnk->params.free_data) {
86 msg_lnk->params.free_data(msg_key, &msg_lnk->params);
87 }
88 BLI_remlink(&msg_key->values, msg_lnk);
89 MEM_freeN(msg_lnk);
90 }
91 }
92
93 if (BLI_listbase_is_empty(&msg_key->values)) {
94 const wmMsg *msg = wm_msg_subscribe_value_msg_cast(msg_key);
95 wmMsgTypeInfo *info = &wm_msg_types[msg->type];
96 BLI_remlink(&mbus->messages, msg_key);
97 bool ok = BLI_gset_remove(mbus->messages_gset[msg->type], msg_key, info->gset.key_free_fn);
98 BLI_assert(ok);
100 }
101 }
102}
103
104void WM_msg_dump(wmMsgBus *mbus, const char *info_str)
105{
106 printf(">>>> %s\n", info_str);
108 const wmMsg *msg = wm_msg_subscribe_value_msg_cast(key);
109 const wmMsgTypeInfo *info = &wm_msg_types[msg->type];
110 info->repr(stdout, key);
111 }
112 printf("<<<< %s\n", info_str);
113}
114
116{
117 if (mbus->messages_tag_count == 0) {
118 // printf("msgbus: skipping\n");
119 return;
120 }
121
122 if (false) {
123 WM_msg_dump(mbus, __func__);
124 }
125
126 // uint a = 0, b = 0;
128 LISTBASE_FOREACH (wmMsgSubscribeValueLink *, msg_lnk, &key->values) {
129 if (msg_lnk->params.tag) {
130 msg_lnk->params.notify(C, key, &msg_lnk->params);
131 msg_lnk->params.tag = false;
132 mbus->messages_tag_count -= 1;
133 }
134 // b++;
135 }
136 // a++;
137 }
138 BLI_assert(mbus->messages_tag_count == 0);
139 mbus->messages_tag_count = 0;
140 // printf("msgbus: keys=%u values=%u\n", a, b);
141}
142
144 const wmMsgSubscribeKey *msg_key_test,
145 const wmMsgSubscribeValue *msg_val_params)
146{
147 const uint type = wm_msg_subscribe_value_msg_cast(msg_key_test)->type;
148 const wmMsgTypeInfo *info = &wm_msg_types[type];
150
151 BLI_assert(wm_msg_subscribe_value_msg_cast(msg_key_test)->id != nullptr);
152
153 void **r_key;
154 if (!BLI_gset_ensure_p_ex(mbus->messages_gset[type], msg_key_test, &r_key)) {
155 key = static_cast<wmMsgSubscribeKey *>(*r_key = MEM_mallocN(info->msg_key_size, __func__));
156 memcpy(key, msg_key_test, info->msg_key_size);
157 BLI_addtail(&mbus->messages, key);
158 }
159 else {
160 key = static_cast<wmMsgSubscribeKey *>(*r_key);
162 if ((msg_lnk->params.notify == msg_val_params->notify) &&
163 (msg_lnk->params.owner == msg_val_params->owner) &&
164 (msg_lnk->params.user_data == msg_val_params->user_data))
165 {
166 return key;
167 }
168 }
169 }
170
171 wmMsgSubscribeValueLink *msg_lnk = static_cast<wmMsgSubscribeValueLink *>(
172 MEM_mallocN(sizeof(wmMsgSubscribeValueLink), __func__));
173 msg_lnk->params = *msg_val_params;
174 BLI_addtail(&key->values, msg_lnk);
175 return key;
176}
177
179{
181 2,
182 "tagging subscribers: (ptr=%p, len=%d)",
183 msg_key,
184 BLI_listbase_count(&msg_key->values));
185
186 LISTBASE_FOREACH (wmMsgSubscribeValueLink *, msg_lnk, &msg_key->values) {
187 if (false) { /* Make an option? */
188 msg_lnk->params.notify(nullptr, msg_key, &msg_lnk->params);
189 }
190 else {
191 if (msg_lnk->params.tag == false) {
192 msg_lnk->params.tag = true;
193 mbus->messages_tag_count += 1;
194 }
195 }
196 }
197}
198
199void WM_msg_id_update(wmMsgBus *mbus, ID *id_src, ID *id_dst)
200{
201 for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
202 wmMsgTypeInfo *info = &wm_msg_types[i];
203 if (info->update_by_id != nullptr) {
204 info->update_by_id(mbus, id_src, id_dst);
205 }
206 }
207}
208
209void WM_msg_id_remove(wmMsgBus *mbus, const ID *id)
210{
211 for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
212 wmMsgTypeInfo *info = &wm_msg_types[i];
213 if (info->remove_by_id != nullptr) {
214 info->remove_by_id(mbus, id);
215 }
216 }
217}
218
221/* -------------------------------------------------------------------------- */
228{
229 if (msg_lnk->params.free_data) {
230 msg_lnk->params.free_data(msg_key, &msg_lnk->params);
231 }
232 BLI_remlink(&msg_key->values, msg_lnk);
233 MEM_freeN(msg_lnk);
234}
235
#define BLI_assert(a)
Definition BLI_assert.h:50
bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key)
Definition BLI_ghash.c:971
GSet * BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:936
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.c:1034
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.c:999
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
Read Guarded memory(de)allocation.
CLG_LogRef * WM_LOG_MSGBUS_SUB
#define printf
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
Definition DNA_ID.h:413
void * first
GSet * messages_gset[WM_MSG_TYPE_NUM]
wmMsgSubscribeKey * next
wmMsgSubscribeValueFreeDataFn free_data
struct wmMsgTypeInfo::@1392 gset
void(* remove_by_id)(wmMsgBus *mbus, const ID *id)
void(* update_by_id)(wmMsgBus *mbus, ID *id_src, ID *id_dst)
void(* repr)(FILE *stream, const wmMsgSubscribeKey *msg_key)
unsigned int(* hash_fn)(const void *msg)
void(* key_free_fn)(void *key)
bool(* cmp_fn)(const void *a, const void *b)
unsigned int type
void WM_msgbus_destroy(wmMsgBus *mbus)
void(*)(wmMsgTypeInfo *) wmMsgTypeInitFn
static wmMsgTypeInitFn wm_msg_init_fn[WM_MSG_TYPE_NUM]
static wmMsgTypeInfo wm_msg_types[WM_MSG_TYPE_NUM]
void WM_msg_publish_with_key(wmMsgBus *mbus, wmMsgSubscribeKey *msg_key)
void WM_msg_id_update(wmMsgBus *mbus, ID *id_src, ID *id_dst)
void WM_msgbus_handle(wmMsgBus *mbus, bContext *C)
void WM_msg_id_remove(wmMsgBus *mbus, const ID *id)
void wm_msg_subscribe_value_free(wmMsgSubscribeKey *msg_key, wmMsgSubscribeValueLink *msg_lnk)
wmMsgBus * WM_msgbus_create()
void WM_msgbus_clear_by_owner(wmMsgBus *mbus, void *owner)
wmMsgSubscribeKey * WM_msg_subscribe_with_key(wmMsgBus *mbus, const wmMsgSubscribeKey *msg_key_test, const wmMsgSubscribeValue *msg_val_params)
void WM_msgbus_types_init()
void WM_msg_dump(wmMsgBus *mbus, const char *info_str)
#define WM_MSG_TYPE_NUM
BLI_INLINE const wmMsg * wm_msg_subscribe_value_msg_cast(const wmMsgSubscribeKey *key)
void WM_msgtypeinfo_init_rna(wmMsgTypeInfo *msgtype_info)
void WM_msgtypeinfo_init_static(wmMsgTypeInfo *msgtype_info)