polar-objc 5.44
An Objective-C runtime library
Loading...
Searching...
No Matches
polar-runtime-service-thread.c
1/* Internal API: runtime service thread for polar-objc.
2 Copyright (C) 2022-2025 Michael Malicoat <[email protected]>
3
4 This file is part of polar-objc.
5
6 polar-objc is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
8
9 polar-objc is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
10 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 details.
12
13 You should have received a copy of the GNU General Public License along with this program; see the file LICENSE. If
14 not, see <http://www.gnu.org/licenses/>.
15*/
16
17// Private =============================================================================================================
18
19#define POLAR_MSG_SERVICE_READY 0xFFFFFF51
20#define POLAR_MSG_SERVICE_SHUTDOWN 0xFFFFFF5F
21
22// These variables are all initialized in polar_runtime_service_thread_init()
23thrd_t polar_id_main_thread = (thrd_t)0;
24thrd_t polar_id_rts_thread = (thrd_t)0;
25polar_thread_message_queue *polar_inbox_rts_thread = NULL;
26
27// This variable is initialized in polar_runtime_service_thread_init()
28static polar_thread_message_queue *polar_inbox_main_thread = NULL;
29
30polar_runtime_service *polar_array_runtime_services[ POLAR_ID_SERVICE_LAST ] =
31{
32 NULL,
33
34 // These are replaced with the corresponding instance of each class by polar_runtime_service_thread_init_services()
35 (polar_runtime_service *)polar_runtime_service_dispatch_get_type,
36 (polar_runtime_service *)polar_runtime_service_memory_disposal_get_type,
37 (polar_runtime_service *)polar_runtime_service_module_get_type,
38 (polar_runtime_service *)polar_runtime_service_selector_get_type,
39 (polar_runtime_service *)polar_runtime_service_thread_sync_get_type,
40 (polar_runtime_service *)polar_runtime_service_type_registry_get_type,
41 (polar_runtime_service *)polar_runtime_service_type_work_get_type
42};
43
44// Called by polar_runtime_service_thread()
45POLAR_FUNCTION_INTERNAL void
46polar_runtime_service_thread_init_services( void )
47{
48 polar_func_internal_type_get_type service_get_type;
49 intptr_t i;
50
51 for( i = POLAR_ID_SERVICE_FIRST; i < POLAR_ID_SERVICE_LAST; i++ )
52 {
53 service_get_type = (polar_func_internal_type_get_type)polar_array_runtime_services[i];
54 polar_array_runtime_services[i] = (polar_runtime_service *)polar_runtime_object_new( service_get_type() );
55 }
56
57 POLAR_DEBUG_FUNCTION_END;
58}
59
60// Called by polar_runtime_service_thread()
61POLAR_FUNCTION_INTERNAL void
62polar_runtime_service_thread_finalize_services( void )
63{
64 polar_runtime_object *service_current;
65 intptr_t i;
66
67 for( i = (POLAR_ID_SERVICE_LAST - 1); i > POLAR_ID_SERVICE_NONE; i-- )
68 {
69 service_current = (polar_runtime_object *)( polar_array_runtime_services[i] );
70
71 if( service_current != NULL )
72 {
73 polar_runtime_object_free(service_current);
74 polar_array_runtime_services[i] = NULL;
75 }
76 }
77
78 POLAR_DEBUG_FUNCTION_END;
79}
80
81OBJC_FUNCTION_HOTSPOT void *
82polar_runtime_service_thread( void *thread_entry_data OBJC_IGNORE_UNUSED )
83{
84 polar_thread_message *service_request;
85 uintptr_t id_service_desired, id_operation_desired;
86
87 // Initialize our services
88 polar_runtime_service_thread_init_services();
89
90 // Let the main thread know we're ready to receive messages
91 service_request = polar_thread_message_new(POLAR_MSG_SERVICE_READY, 0, NULL);
92 polar_thread_message_send(service_request, polar_inbox_main_thread);
93
94 // Wait for work to become available
95 service_request = polar_thread_message_queue_message_wait(polar_inbox_rts_thread);
96 while( service_request->subject_message != POLAR_MSG_SERVICE_SHUTDOWN )
97 {
98 // Handle the request
99 id_service_desired = ( service_request->subject_message >> POLAR_SHIFT_SERVICE_REQUEST );
100 assert( id_service_desired > POLAR_ID_SERVICE_NONE );
101 assert( id_service_desired < POLAR_ID_SERVICE_LAST );
102
103 id_operation_desired = ( service_request->subject_message & POLAR_MASK_REQUEST_OPERATION );
104
105 polar_runtime_service_request_handle( polar_array_runtime_services[id_service_desired], id_operation_desired,
106 service_request, service_request->message_data );
107
108 // Wait for work to become available
109 service_request = polar_thread_message_queue_message_wait(polar_inbox_rts_thread);
110 }
111
112 // Free the "shutdown" message
113 polar_runtime_object_free( (polar_runtime_object *)service_request );
114
115 // Finalize our services
116 polar_runtime_service_thread_finalize_services();
117
118 // Return NULL and end the thread
119 return NULL;
120}
121
122// Public ==============================================================================================================
123
124// Called by polar_init()
125POLAR_FUNCTION_INTERNAL intptr_t
126polar_runtime_service_thread_init( void )
127{
128 polar_thread_message *message_service_thread_ready;
129
130 // Establish a message queue for the main thread
131 polar_id_main_thread = thrd_current();
132 polar_inbox_main_thread = polar_thread_current_get_inbox();
133
134 // Establish a message queue for the runtime service thread
135 polar_inbox_rts_thread = polar_thread_message_queue_new(polar_id_main_thread);
136
137 // Spin off the runtime service thread
138 polar_thread_split( &polar_id_rts_thread, (polar_func_thread_enter)polar_runtime_service_thread, NULL,
139 polar_inbox_rts_thread );
140
141 if( polar_id_rts_thread != (thrd_t) 0 )
142 ;
143
144 else
145 return -1;
146
147 // Wait for the runtime service thread to report that it's ready for work
148 message_service_thread_ready = polar_thread_message_queue_message_wait(polar_inbox_main_thread);
149 assert( message_service_thread_ready->subject_message == POLAR_MSG_SERVICE_READY );
150
151 polar_runtime_object_free( (polar_runtime_object *)message_service_thread_ready );
152
153 POLAR_DEBUG_FUNCTION_END;
154
155 return 0;
156}
157
158// Called by polar_finalize()
159POLAR_FUNCTION_INTERNAL void
160polar_runtime_service_thread_finalize( void )
161{
162 polar_thread_message *message_service_thread_shutdown;
163
164 if( polar_id_rts_thread != (thrd_t)0 )
165 {
166 // Shut down the runtime service thread
167 message_service_thread_shutdown = polar_thread_message_new(POLAR_MSG_SERVICE_SHUTDOWN, 0, NULL);
168 polar_thread_message_send(message_service_thread_shutdown, polar_inbox_rts_thread);
169
170 // Wait for the service thread to shut down gracefully
171 thrd_join(polar_id_rts_thread, NULL);
172 }
173
174 POLAR_DEBUG_FUNCTION_END;
175}
DWORD thrd_t
Definition polar-windows-platform-threading.h:111
intptr_t thrd_join(thrd_t id_thread_target, intptr_t *__p_retval_unused)
Definition polar-windows-platform-threading.c:178
static thrd_t thrd_current(void)
Definition polar-windows-platform-threading.h:134
Definition polar-runtime-object.h:31
Definition polar-runtime-service.h:28
Definition polar-thread-message-queue.h:23
Definition polar-thread-message.h:25