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-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 "physics_2d_server_wrap_mt.h"
31
32 #include "os/os.h"
33
thread_exit()34 void Physics2DServerWrapMT::thread_exit() {
35
36 exit = true;
37 }
38
thread_step(float p_delta)39 void Physics2DServerWrapMT::thread_step(float p_delta) {
40
41 physics_2d_server->step(p_delta);
42 step_sem->post();
43 }
44
_thread_callback(void * _instance)45 void Physics2DServerWrapMT::_thread_callback(void *_instance) {
46
47 Physics2DServerWrapMT *vsmt = reinterpret_cast<Physics2DServerWrapMT *>(_instance);
48
49 vsmt->thread_loop();
50 }
51
thread_loop()52 void Physics2DServerWrapMT::thread_loop() {
53
54 server_thread = Thread::get_caller_ID();
55
56 OS::get_singleton()->make_rendering_thread();
57
58 physics_2d_server->init();
59
60 exit = false;
61 step_thread_up = true;
62 while (!exit) {
63 // flush commands one by one, until exit is requested
64 command_queue.wait_and_flush_one();
65 }
66
67 command_queue.flush_all(); // flush all
68
69 physics_2d_server->finish();
70 }
71
72 /* EVENT QUEUING */
73
step(float p_step)74 void Physics2DServerWrapMT::step(float p_step) {
75
76 if (create_thread) {
77
78 command_queue.push(this, &Physics2DServerWrapMT::thread_step, p_step);
79 } else {
80
81 command_queue.flush_all(); //flush all pending from other threads
82 physics_2d_server->step(p_step);
83 }
84 }
85
sync()86 void Physics2DServerWrapMT::sync() {
87
88 if (step_sem) {
89 if (first_frame)
90 first_frame = false;
91 else
92 step_sem->wait(); //must not wait if a step was not issued
93 }
94 physics_2d_server->sync();
95 }
96
flush_queries()97 void Physics2DServerWrapMT::flush_queries() {
98
99 physics_2d_server->flush_queries();
100 }
101
end_sync()102 void Physics2DServerWrapMT::end_sync() {
103
104 physics_2d_server->end_sync();
105 }
106
init()107 void Physics2DServerWrapMT::init() {
108
109 if (create_thread) {
110
111 step_sem = Semaphore::create();
112 print_line("Creating physics 2D thread");
113 //OS::get_singleton()->release_rendering_thread();
114 if (create_thread) {
115 thread = Thread::create(_thread_callback, this);
116 print_line("Starting physics 2D thread");
117 }
118 while (!step_thread_up) {
119 OS::get_singleton()->delay_usec(1000);
120 }
121 print_line("Done physics 2D thread");
122 } else {
123
124 physics_2d_server->init();
125 }
126 }
127
finish()128 void Physics2DServerWrapMT::finish() {
129
130 if (thread) {
131
132 command_queue.push(this, &Physics2DServerWrapMT::thread_exit);
133 Thread::wait_to_finish(thread);
134 memdelete(thread);
135
136 /*
137 shape_free_cached_ids();
138 area_free_cached_ids();
139 body_free_cached_ids();
140 pin_joint_free_cached_ids();
141 groove_joint_free_cached_ids();
142 damped_string_free_cached_ids();
143 */
144 thread = NULL;
145 } else {
146 physics_2d_server->finish();
147 }
148
149 if (step_sem)
150 memdelete(step_sem);
151 }
152
Physics2DServerWrapMT(Physics2DServer * p_contained,bool p_create_thread)153 Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer *p_contained, bool p_create_thread) :
154 command_queue(p_create_thread) {
155
156 physics_2d_server = p_contained;
157 create_thread = p_create_thread;
158 thread = NULL;
159 step_sem = NULL;
160 step_pending = 0;
161 step_thread_up = false;
162 alloc_mutex = Mutex::create();
163
164 shape_pool_max_size = GLOBAL_DEF("core/thread_rid_pool_prealloc", 20);
165 area_pool_max_size = GLOBAL_DEF("core/thread_rid_pool_prealloc", 20);
166 body_pool_max_size = GLOBAL_DEF("core/thread_rid_pool_prealloc", 20);
167 pin_joint_pool_max_size = GLOBAL_DEF("core/thread_rid_pool_prealloc", 20);
168 groove_joint_pool_max_size = GLOBAL_DEF("core/thread_rid_pool_prealloc", 20);
169 damped_spring_joint_pool_max_size = GLOBAL_DEF("core/thread_rid_pool_prealloc", 20);
170
171 if (!p_create_thread) {
172 server_thread = Thread::get_caller_ID();
173 } else {
174 server_thread = 0;
175 }
176
177 main_thread = Thread::get_caller_ID();
178 first_frame = true;
179 }
180
~Physics2DServerWrapMT()181 Physics2DServerWrapMT::~Physics2DServerWrapMT() {
182
183 memdelete(physics_2d_server);
184 memdelete(alloc_mutex);
185 //finish();
186 }
187