Blender  V3.3
wm_message_bus.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <string.h>
8 
9 #include "CLG_log.h"
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "BLI_listbase.h"
14 #include "BLI_utildefines.h"
15 
16 #include "BLI_ghash.h"
17 
18 #include "WM_types.h"
19 
22 
23 /* -------------------------------------------------------------------------- */
28 
30 
34 };
35 
37 {
38  for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
40  }
41 }
42 
44 {
45  struct wmMsgBus *mbus = MEM_callocN(sizeof(*mbus), __func__);
46  const uint gset_reserve = 512;
47  for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
48  wmMsgTypeInfo *info = &wm_msg_types[i];
49  mbus->messages_gset[i] = BLI_gset_new_ex(
50  info->gset.hash_fn, info->gset.cmp_fn, __func__, gset_reserve);
51  }
52  return mbus;
53 }
54 
55 void WM_msgbus_destroy(struct wmMsgBus *mbus)
56 {
57  for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
58  wmMsgTypeInfo *info = &wm_msg_types[i];
60  }
61  MEM_freeN(mbus);
62 }
63 
64 void WM_msgbus_clear_by_owner(struct wmMsgBus *mbus, void *owner)
65 {
66  wmMsgSubscribeKey *msg_key, *msg_key_next;
67  for (msg_key = mbus->messages.first; msg_key; msg_key = msg_key_next) {
68  msg_key_next = msg_key->next;
69 
70  wmMsgSubscribeValueLink *msg_lnk_next;
71  for (wmMsgSubscribeValueLink *msg_lnk = msg_key->values.first; msg_lnk;
72  msg_lnk = msg_lnk_next) {
73  msg_lnk_next = msg_lnk->next;
74  if (msg_lnk->params.owner == owner) {
75  if (msg_lnk->params.tag) {
76  mbus->messages_tag_count -= 1;
77  }
78  if (msg_lnk->params.free_data) {
79  msg_lnk->params.free_data(msg_key, &msg_lnk->params);
80  }
81  BLI_remlink(&msg_key->values, msg_lnk);
82  MEM_freeN(msg_lnk);
83  }
84  }
85 
86  if (BLI_listbase_is_empty(&msg_key->values)) {
87  const wmMsg *msg = wm_msg_subscribe_value_msg_cast(msg_key);
88  wmMsgTypeInfo *info = &wm_msg_types[msg->type];
89  BLI_remlink(&mbus->messages, msg_key);
90  bool ok = BLI_gset_remove(mbus->messages_gset[msg->type], msg_key, info->gset.key_free_fn);
91  BLI_assert(ok);
93  }
94  }
95 }
96 
97 void WM_msg_dump(struct wmMsgBus *mbus, const char *info_str)
98 {
99  printf(">>>> %s\n", info_str);
100  LISTBASE_FOREACH (wmMsgSubscribeKey *, key, &mbus->messages) {
101  const wmMsg *msg = wm_msg_subscribe_value_msg_cast(key);
102  const wmMsgTypeInfo *info = &wm_msg_types[msg->type];
103  info->repr(stdout, key);
104  }
105  printf("<<<< %s\n", info_str);
106 }
107 
108 void WM_msgbus_handle(struct wmMsgBus *mbus, struct bContext *C)
109 {
110  if (mbus->messages_tag_count == 0) {
111  // printf("msgbus: skipping\n");
112  return;
113  }
114 
115  if (false) {
116  WM_msg_dump(mbus, __func__);
117  }
118 
119  // uint a = 0, b = 0;
120  LISTBASE_FOREACH (wmMsgSubscribeKey *, key, &mbus->messages) {
121  LISTBASE_FOREACH (wmMsgSubscribeValueLink *, msg_lnk, &key->values) {
122  if (msg_lnk->params.tag) {
123  msg_lnk->params.notify(C, key, &msg_lnk->params);
124  msg_lnk->params.tag = false;
125  mbus->messages_tag_count -= 1;
126  }
127  // b++;
128  }
129  // a++;
130  }
131  BLI_assert(mbus->messages_tag_count == 0);
132  mbus->messages_tag_count = 0;
133  // printf("msgbus: keys=%u values=%u\n", a, b);
134 }
135 
137  const wmMsgSubscribeKey *msg_key_test,
138  const wmMsgSubscribeValue *msg_val_params)
139 {
140  const uint type = wm_msg_subscribe_value_msg_cast(msg_key_test)->type;
141  const wmMsgTypeInfo *info = &wm_msg_types[type];
142  wmMsgSubscribeKey *key;
143 
144  BLI_assert(wm_msg_subscribe_value_msg_cast(msg_key_test)->id != NULL);
145 
146  void **r_key;
147  if (!BLI_gset_ensure_p_ex(mbus->messages_gset[type], msg_key_test, &r_key)) {
148  key = *r_key = MEM_mallocN(info->msg_key_size, __func__);
149  memcpy(key, msg_key_test, info->msg_key_size);
150  BLI_addtail(&mbus->messages, key);
151  }
152  else {
153  key = *r_key;
154  LISTBASE_FOREACH (wmMsgSubscribeValueLink *, msg_lnk, &key->values) {
155  if ((msg_lnk->params.notify == msg_val_params->notify) &&
156  (msg_lnk->params.owner == msg_val_params->owner) &&
157  (msg_lnk->params.user_data == msg_val_params->user_data)) {
158  return key;
159  }
160  }
161  }
162 
163  wmMsgSubscribeValueLink *msg_lnk = MEM_mallocN(sizeof(wmMsgSubscribeValueLink), __func__);
164  msg_lnk->params = *msg_val_params;
165  BLI_addtail(&key->values, msg_lnk);
166  return key;
167 }
168 
170 {
172  2,
173  "tagging subscribers: (ptr=%p, len=%d)",
174  msg_key,
175  BLI_listbase_count(&msg_key->values));
176 
177  LISTBASE_FOREACH (wmMsgSubscribeValueLink *, msg_lnk, &msg_key->values) {
178  if (false) { /* make an option? */
179  msg_lnk->params.notify(NULL, msg_key, &msg_lnk->params);
180  }
181  else {
182  if (msg_lnk->params.tag == false) {
183  msg_lnk->params.tag = true;
184  mbus->messages_tag_count += 1;
185  }
186  }
187  }
188 }
189 
190 void WM_msg_id_update(struct wmMsgBus *mbus, struct ID *id_src, struct ID *id_dst)
191 {
192  for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
193  wmMsgTypeInfo *info = &wm_msg_types[i];
194  if (info->update_by_id != NULL) {
195  info->update_by_id(mbus, id_src, id_dst);
196  }
197  }
198 }
199 
200 void WM_msg_id_remove(struct wmMsgBus *mbus, const struct ID *id)
201 {
202  for (uint i = 0; i < WM_MSG_TYPE_NUM; i++) {
203  wmMsgTypeInfo *info = &wm_msg_types[i];
204  if (info->remove_by_id != NULL) {
205  info->remove_by_id(mbus, id);
206  }
207  }
208 }
209 
212 /* -------------------------------------------------------------------------- */
219 {
220  if (msg_lnk->params.free_data) {
221  msg_lnk->params.free_data(msg_key, &msg_lnk->params);
222  }
223  BLI_remlink(&msg_key->values, msg_lnk);
224  MEM_freeN(msg_lnk);
225 }
226 
#define BLI_assert(a)
Definition: BLI_assert.h:46
bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key)
Definition: BLI_ghash.c:974
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:939
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1002
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED_VARS_NDEBUG(...)
#define CLOG_INFO(clg_ref, level,...)
Definition: CLG_log.h:187
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
struct CLG_LogRef * WM_LOG_MSGBUS_SUB
SyclQueue void void size_t num_bytes void
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
Definition: DNA_ID.h:368
void * first
Definition: DNA_listBase.h:31
struct GSet * messages_gset[WM_MSG_TYPE_NUM]
struct wmMsgSubscribeKey * next
wmMsgSubscribeValueFreeDataFn free_data
wmMsgNotifyFn notify
void(* remove_by_id)(struct wmMsgBus *mbus, const struct ID *id)
void(* update_by_id)(struct wmMsgBus *mbus, struct ID *id_src, struct ID *id_dst)
void(* repr)(FILE *stream, const struct wmMsgSubscribeKey *msg_key)
struct wmMsgTypeInfo::@1202 gset
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_msg_id_update(struct wmMsgBus *mbus, struct ID *id_src, struct ID *id_dst)
void WM_msgbus_clear_by_owner(struct wmMsgBus *mbus, void *owner)
static wmMsgTypeInitFn wm_msg_init_fn[WM_MSG_TYPE_NUM]
void WM_msgbus_destroy(struct wmMsgBus *mbus)
static wmMsgTypeInfo wm_msg_types[WM_MSG_TYPE_NUM]
void WM_msg_dump(struct wmMsgBus *mbus, const char *info_str)
void WM_msgbus_types_init(void)
void WM_msg_publish_with_key(struct wmMsgBus *mbus, wmMsgSubscribeKey *msg_key)
void WM_msg_id_remove(struct wmMsgBus *mbus, const struct ID *id)
wmMsgSubscribeKey * WM_msg_subscribe_with_key(struct wmMsgBus *mbus, const wmMsgSubscribeKey *msg_key_test, const wmMsgSubscribeValue *msg_val_params)
void WM_msgbus_handle(struct wmMsgBus *mbus, struct bContext *C)
void wm_msg_subscribe_value_free(wmMsgSubscribeKey *msg_key, wmMsgSubscribeValueLink *msg_lnk)
void(* wmMsgTypeInitFn)(wmMsgTypeInfo *)
struct wmMsgBus * WM_msgbus_create(void)
#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)