1 /*************************************************************************/
2 /*  event_queue.cpp                                                      */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 #include "event_queue.h"
31 
push_call(uint32_t p_instance_ID,const StringName & p_method,VARIANT_ARG_DECLARE)32 Error EventQueue::push_call(uint32_t p_instance_ID, const StringName &p_method, VARIANT_ARG_DECLARE) {
33 
34 	uint8_t room_needed = sizeof(Event);
35 	int args = 0;
36 	if (p_arg5.get_type() != Variant::NIL)
37 		args = 5;
38 	else if (p_arg4.get_type() != Variant::NIL)
39 		args = 4;
40 	else if (p_arg3.get_type() != Variant::NIL)
41 		args = 3;
42 	else if (p_arg2.get_type() != Variant::NIL)
43 		args = 2;
44 	else if (p_arg1.get_type() != Variant::NIL)
45 		args = 1;
46 	else
47 		args = 0;
48 
49 	room_needed += sizeof(Variant) * args;
50 
51 	ERR_FAIL_COND_V((buffer_end + room_needed) >= buffer_size, ERR_OUT_OF_MEMORY);
52 	Event *ev = memnew_placement(&event_buffer[buffer_end], Event);
53 	ev->args = args;
54 	ev->instance_ID = p_instance_ID;
55 	ev->method = p_method;
56 
57 	buffer_end += sizeof(Event);
58 
59 	if (args >= 1) {
60 
61 		Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
62 		buffer_end += sizeof(Variant);
63 		*v = p_arg1;
64 	}
65 
66 	if (args >= 2) {
67 
68 		Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
69 		buffer_end += sizeof(Variant);
70 		*v = p_arg2;
71 	}
72 
73 	if (args >= 3) {
74 
75 		Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
76 		buffer_end += sizeof(Variant);
77 		*v = p_arg3;
78 	}
79 
80 	if (args >= 4) {
81 
82 		Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
83 		buffer_end += sizeof(Variant);
84 		*v = p_arg4;
85 	}
86 
87 	if (args >= 5) {
88 
89 		Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
90 		buffer_end += sizeof(Variant);
91 		*v = p_arg5;
92 	}
93 
94 	if (buffer_end > buffer_max_used)
95 		buffer_max_used = buffer_end;
96 
97 	return OK;
98 }
99 
flush_events()100 void EventQueue::flush_events() {
101 
102 	uint32_t read_pos = 0;
103 
104 	while (read_pos < buffer_end) {
105 
106 		Event *event = (Event *)&event_buffer[read_pos];
107 		Variant *args = (Variant *)(event + 1);
108 		Object *obj = ObjectDB::get_instance(event->instance_ID);
109 
110 		if (obj) {
111 			// events don't expect a return value
112 			obj->call(event->method,
113 					(event->args >= 1) ? args[0] : Variant(),
114 					(event->args >= 2) ? args[1] : Variant(),
115 					(event->args >= 3) ? args[2] : Variant(),
116 					(event->args >= 4) ? args[3] : Variant(),
117 					(event->args >= 5) ? args[4] : Variant());
118 		}
119 
120 		if (event->args >= 1) args[0].~Variant();
121 		if (event->args >= 2) args[1].~Variant();
122 		if (event->args >= 3) args[2].~Variant();
123 		if (event->args >= 4) args[3].~Variant();
124 		if (event->args >= 5) args[4].~Variant();
125 		event->~Event();
126 
127 		read_pos += sizeof(Event) + sizeof(Variant) * event->args;
128 	}
129 
130 	buffer_end = 0; // reset buffer
131 }
132 
EventQueue(uint32_t p_buffer_size)133 EventQueue::EventQueue(uint32_t p_buffer_size) {
134 
135 	buffer_end = 0;
136 	buffer_max_used = 0;
137 	buffer_size = p_buffer_size;
138 	event_buffer = memnew_arr(uint8_t, buffer_size);
139 }
~EventQueue()140 EventQueue::~EventQueue() {
141 
142 	uint32_t read_pos = 0;
143 
144 	while (read_pos < buffer_end) {
145 
146 		Event *event = (Event *)&event_buffer[read_pos];
147 		Variant *args = (Variant *)(event + 1);
148 		for (int i = 0; i < event->args; i++)
149 			args[i].~Variant();
150 		event->~Event();
151 
152 		read_pos += sizeof(Event) + sizeof(Variant) * event->args;
153 	}
154 
155 	memdelete_arr(event_buffer);
156 	event_buffer = NULL;
157 }
158