efl

Форк
0
/
eo_ptr_indirection.c 
195 строк · 7.0 Кб
1
#ifdef HAVE_CONFIG_H
2
# include <config.h>
3
#endif
4

5
#include "eo_ptr_indirection.h"
6

7
extern Eina_Thread _efl_object_main_thread;
8

9
//////////////////////////////////////////////////////////////////////////
10

11
Eina_TLS          _eo_table_data;
12
Eo_Id_Data       *_eo_table_data_shared = NULL;
13
Eo_Id_Table_Data *_eo_table_data_shared_data = NULL;
14

15
//////////////////////////////////////////////////////////////////////////
16

17
void
18
_eo_pointer_error(const Eo *obj_id, const char *func_name, const char *file, int line, const char *fmt, ...)
19
{
20
   /* NOTE: this function exists to allow easy breakpoint on pointer errors */
21
   va_list args;
22
   va_start(args, fmt);
23
   eina_log_vprint(_eo_log_dom, EINA_LOG_LEVEL_ERR, file, func_name, line, fmt, args);
24
   va_end(args);
25
   _eo_log_obj_report((Eo_Id)obj_id, EINA_LOG_LEVEL_ERR, func_name, file, line);
26
}
27

28
static void
29
_eo_obj_pointer_invalid(const Eo_Id obj_id,
30
                        Eo_Id_Data *data,
31
                        unsigned char domain,
32
                        const char *func_name,
33
                        const char *file,
34
                        int line)
35
{
36
   Eina_Thread thread = eina_thread_self();
37
   const char *tself = "main";
38
   const char *type = "object";
39
   const char *reason = "This ID has probably been deleted";
40
   char tbuf[128];
41
   if (obj_id & MASK_CLASS_TAG) type = "class";
42
   if (thread != _efl_object_main_thread)
43
     {
44
        snprintf(tbuf, sizeof(tbuf), "%p", (void *)thread);
45
        tself = tbuf;
46
     }
47

48
   if (!data->tables[(int)data->local_domain])
49
     reason = "This ID does not seem to belong to this thread";
50
   else if ((Efl_Id_Domain)domain == EFL_ID_DOMAIN_SHARED)
51
     reason = "This shared ID has probably been deleted";
52

53
   eina_log_print(_eo_log_dom, EINA_LOG_LEVEL_ERR,
54
                  file, func_name, line,
55
                  "Eo ID %p is not a valid %s. "
56
                  "Current thread: %s. "
57
                  "%s or this was never a valid %s ID. "
58
                  "(domain=%i, current_domain=%i, local_domain=%i, "
59
                  "available_domains=[%s %s %s %s], "
60
                  "generation=%lx, id=%lx, ref=%i)",
61
                  (void *)obj_id,
62
                  type,
63
                  tself,
64
                  reason,
65
                  type,
66
                  (int)domain,
67
                  (int)data->domain_stack[data->stack_top],
68
                  (int)data->local_domain,
69
                  (data->tables[0]) ? "0" : " ",
70
                  (data->tables[1]) ? "1" : " ",
71
                  (data->tables[2]) ? "2" : " ",
72
                  (data->tables[3]) ? "3" : " ",
73
                  (unsigned long)(obj_id & MASK_GENERATIONS),
74
                  (unsigned long)(obj_id >> SHIFT_ENTRY_ID) & (MAX_ENTRY_ID | MAX_TABLE_ID | MAX_MID_TABLE_ID),
75
                  (int)(obj_id >> REF_TAG_SHIFT) & 0x1);
76
   _eo_log_obj_report(obj_id, EINA_LOG_LEVEL_ERR, func_name, file, line);
77
}
78

79
_Eo_Object *
80
_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line)
81
{
82
   _Eo_Id_Entry *entry;
83
   Generation_Counter generation;
84
   Table_Index mid_table_id, table_id, entry_id;
85
   Eo_Id tag_bit;
86
   Eo_Id_Data *data;
87
   Eo_Id_Table_Data *tdata;
88
   unsigned char domain;
89

90
   // NULL objects will just be sensibly ignored. not worth complaining
91
   // every single time.
92

93
   data = _eo_table_data_get();
94
   EINA_PREFETCH(&(data->tables[0]));
95
   domain = (obj_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
96
   tdata = _eo_table_data_table_get(data, domain);
97
   if (EINA_UNLIKELY(!tdata)) goto err;
98
   _eo_cache_prefetch(tdata);
99

100
   if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED))
101
     {
102
        _Eo_Object *obj;
103

104
        obj = _eo_cache_find(tdata, obj_id);
105
        if (obj) return obj;
106

107
        mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID;
108
        EINA_PREFETCH(&(tdata->eo_ids_tables[mid_table_id])); //prefetch for line 119
109
        table_id = (obj_id >> SHIFT_TABLE_ID) & MASK_TABLE_ID;
110
        EINA_PREFETCH((tdata->eo_ids_tables[mid_table_id] + table_id)); //prefetch for line 121
111
        entry_id = (obj_id >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID;
112
        generation = obj_id & MASK_GENERATIONS;
113

114
        // get tag bit to check later down below - pipelining
115
        tag_bit = (obj_id) & MASK_OBJ_TAG;
116
        if (!obj_id) goto err_null;
117
        else if (!tag_bit) goto err;
118

119
        // Check the validity of the entry
120
        if (tdata->eo_ids_tables[mid_table_id])
121
          {
122
             _Eo_Ids_Table *tab = TABLE_FROM_IDS;
123
             EINA_PREFETCH_NOCACHE(tab); //prefetch for line 125
124
             if (tab)
125
               {
126
                  entry = &(tab->entries[entry_id]);
127
                  if (entry->active && (entry->generation == generation))
128
                    {
129
                       // Cache the result of that lookup
130
                       _eo_cache_store(tdata, obj_id, entry->ptr);
131
                       return entry->ptr;
132
                    }
133
               }
134
          }
135
        goto err;
136
     }
137
   else
138
     {
139
        _Eo_Object *obj;
140

141
        eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
142
        // yes we return keeping the lock locked. that's why
143
        // you must call _eo_obj_pointer_done() wrapped
144
        // by EO_OBJ_DONE() to release
145
        obj = _eo_cache_find(tdata, obj_id);
146
        if (obj) return obj;
147

148
        mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID;
149
        EINA_PREFETCH(&(tdata->eo_ids_tables[mid_table_id]));
150
        table_id = (obj_id >> SHIFT_TABLE_ID) & MASK_TABLE_ID;
151
        EINA_PREFETCH((tdata->eo_ids_tables[mid_table_id] + table_id));
152
        entry_id = (obj_id >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID;
153
        generation = obj_id & MASK_GENERATIONS;
154

155
        // get tag bit to check later down below - pipelining
156
        tag_bit = (obj_id) & MASK_OBJ_TAG;
157
        if (!obj_id) goto err_shared_null;
158
        else if (!tag_bit) goto err_shared;
159

160
        // Check the validity of the entry
161
        if (tdata->eo_ids_tables[mid_table_id])
162
          {
163
             _Eo_Ids_Table *tab = TABLE_FROM_IDS;
164
             EINA_PREFETCH_NOCACHE(tab);
165

166
             if (tab)
167
               {
168
                  entry = &(tab->entries[entry_id]);
169
                  if (entry->active && (entry->generation == generation))
170
                    {
171
                       // Cache the result of that lookup
172
                       _eo_cache_store(tdata, obj_id, entry->ptr);
173
                       // yes we return keeping the lock locked. that's why
174
                       // you must call _eo_obj_pointer_done() wrapped
175
                       // by EO_OBJ_DONE() to release
176
                       return entry->ptr;
177
                    }
178
               }
179
          }
180
        goto err_shared;
181
     }
182
err_shared_null:
183
   eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
184
err_null:
185
   eina_log_print(_eo_log_dom,
186
                  EINA_LOG_LEVEL_DBG,
187
                  file, func_name, line,
188
                  "obj_id is NULL. Possibly unintended access?");
189
   return NULL;
190
err_shared:
191
   eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
192
err:
193
   _eo_obj_pointer_invalid(obj_id, data, domain, func_name, file, line);
194
   return NULL;
195
}
196

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.