1 /*************************************************************************/
2 /* physics_2d_server_wrap_mt.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 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
31 #include "physics_2d_server_wrap_mt.h"
32
33 #include "core/os/os.h"
34
thread_exit()35 void Physics2DServerWrapMT::thread_exit() {
36
37 exit = true;
38 }
39
thread_step(real_t p_delta)40 void Physics2DServerWrapMT::thread_step(real_t p_delta) {
41
42 physics_2d_server->step(p_delta);
43 step_sem->post();
44 }
45
_thread_callback(void * _instance)46 void Physics2DServerWrapMT::_thread_callback(void *_instance) {
47
48 Physics2DServerWrapMT *vsmt = reinterpret_cast<Physics2DServerWrapMT *>(_instance);
49
50 vsmt->thread_loop();
51 }
52
thread_loop()53 void Physics2DServerWrapMT::thread_loop() {
54
55 server_thread = Thread::get_caller_id();
56
57 physics_2d_server->init();
58
59 exit = false;
60 step_thread_up = true;
61 while (!exit) {
62 // flush commands one by one, until exit is requested
63 command_queue.wait_and_flush_one();
64 }
65
66 command_queue.flush_all(); // flush all
67
68 physics_2d_server->finish();
69 }
70
71 /* EVENT QUEUING */
72
step(real_t p_step)73 void Physics2DServerWrapMT::step(real_t p_step) {
74
75 if (create_thread) {
76
77 command_queue.push(this, &Physics2DServerWrapMT::thread_step, p_step);
78 } else {
79
80 command_queue.flush_all(); //flush all pending from other threads
81 physics_2d_server->step(p_step);
82 }
83 }
84
sync()85 void Physics2DServerWrapMT::sync() {
86
87 if (step_sem) {
88 if (first_frame)
89 first_frame = false;
90 else
91 step_sem->wait(); //must not wait if a step was not issued
92 }
93 physics_2d_server->sync();
94 }
95
flush_queries()96 void Physics2DServerWrapMT::flush_queries() {
97
98 physics_2d_server->flush_queries();
99 }
100
end_sync()101 void Physics2DServerWrapMT::end_sync() {
102
103 physics_2d_server->end_sync();
104 }
105
init()106 void Physics2DServerWrapMT::init() {
107
108 if (create_thread) {
109
110 step_sem = Semaphore::create();
111 //OS::get_singleton()->release_rendering_thread();
112 if (create_thread) {
113 thread = Thread::create(_thread_callback, this);
114 }
115 while (!step_thread_up) {
116 OS::get_singleton()->delay_usec(1000);
117 }
118 } else {
119
120 physics_2d_server->init();
121 }
122 }
123
finish()124 void Physics2DServerWrapMT::finish() {
125
126 if (thread) {
127
128 command_queue.push(this, &Physics2DServerWrapMT::thread_exit);
129 Thread::wait_to_finish(thread);
130 memdelete(thread);
131
132 thread = NULL;
133 } else {
134 physics_2d_server->finish();
135 }
136
137 line_shape_free_cached_ids();
138 ray_shape_free_cached_ids();
139 segment_shape_free_cached_ids();
140 circle_shape_free_cached_ids();
141 rectangle_shape_free_cached_ids();
142 capsule_shape_free_cached_ids();
143 convex_polygon_shape_free_cached_ids();
144 concave_polygon_shape_free_cached_ids();
145
146 space_free_cached_ids();
147 area_free_cached_ids();
148 body_free_cached_ids();
149
150 if (step_sem)
151 memdelete(step_sem);
152 }
153
Physics2DServerWrapMT(Physics2DServer * p_contained,bool p_create_thread)154 Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer *p_contained, bool p_create_thread) :
155 command_queue(p_create_thread) {
156
157 physics_2d_server = p_contained;
158 create_thread = p_create_thread;
159 thread = NULL;
160 step_sem = NULL;
161 step_pending = 0;
162 step_thread_up = false;
163 alloc_mutex = Mutex::create();
164
165 pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
166
167 if (!p_create_thread) {
168 server_thread = Thread::get_caller_id();
169 } else {
170 server_thread = 0;
171 }
172
173 main_thread = Thread::get_caller_id();
174 first_frame = true;
175 }
176
~Physics2DServerWrapMT()177 Physics2DServerWrapMT::~Physics2DServerWrapMT() {
178
179 memdelete(physics_2d_server);
180 memdelete(alloc_mutex);
181 //finish();
182 }
183