25
25
#include < unordered_map>
26
26
#include < atomic>
27
27
28
- #include " swoole_thread.h"
29
-
30
28
BEGIN_EXTERN_C ()
31
29
#include " stubs/php_swoole_thread_arginfo.h"
32
30
END_EXTERN_C ()
@@ -45,11 +43,24 @@ static struct {
45
43
46
44
TSRMLS_CACHE_EXTERN ();
47
45
48
- typedef std::thread Thread;
46
+ using swoole::Thread;
47
+
48
+ struct PhpThread {
49
+ std::shared_ptr<Thread> thread;
50
+
51
+ PhpThread () : thread(std::make_shared<Thread>()) {}
52
+
53
+ bool join () {
54
+ if (!thread->joinable ()) {
55
+ return false ;
56
+ }
57
+ thread->join ();
58
+ return true ;
59
+ }
60
+ };
49
61
50
62
struct ThreadObject {
51
- Thread *thread;
52
- pthread_t thread_id;
63
+ PhpThread *pt;
53
64
zend_object std;
54
65
};
55
66
@@ -58,44 +69,35 @@ static void thread_register_stdio_file_handles(bool no_close);
58
69
static thread_local zval thread_argv = {};
59
70
static thread_local JMP_BUF *thread_bailout = nullptr ;
60
71
static std::atomic<size_t > thread_num (1 );
61
- static zend::ConcurrencyHashMap<pthread_t , int > thread_exit_status (-1 );
62
- static zend::ConcurrencyHashMap<pthread_t , bool > thread_living (false );
63
72
64
73
static sw_inline ThreadObject *thread_fetch_object (zend_object *obj) {
65
74
return (ThreadObject *) ((char *) obj - swoole_thread_handlers.offset );
66
75
}
67
76
68
- static pthread_t thread_get_id (zend_object *object) {
69
- zval *res, rv;
70
- res = zend_read_property (swoole_thread_ce, object, ZEND_STRL (" id" ), 1 , &rv);
71
- return (pthread_t ) zval_get_long (res);
77
+ static sw_inline ThreadObject *thread_fetch_object (zval *zobj) {
78
+ return thread_fetch_object (Z_OBJ_P (zobj));
72
79
}
73
80
74
- static pthread_t thread_get_id (zval *zobj ) {
75
- return thread_get_id ( Z_OBJ_P (zobj)) ;
81
+ static sw_inline PhpThread * thread_get_php_thread (zend_object *obj ) {
82
+ return thread_fetch_object (obj)-> pt ;
76
83
}
77
84
78
- static void thread_join (zend_object *object) {
79
- ThreadObject *to = thread_fetch_object (object);
80
- if (to->thread && to->thread ->joinable ()) {
81
- to->thread ->join ();
82
- php_swoole_thread_join (to->thread ->native_handle ());
83
- delete to->thread ;
84
- to->thread = nullptr ;
85
- }
85
+ static sw_inline PhpThread *thread_get_php_thread (zval *zobj) {
86
+ return thread_fetch_object (zobj)->pt ;
86
87
}
87
88
88
89
static void thread_free_object (zend_object *object) {
89
- ThreadObject *to = thread_fetch_object (object);
90
- thread_join (object );
91
- thread_living. del (to-> thread_id ) ;
90
+ auto pt = thread_get_php_thread (object);
91
+ pt-> join ( );
92
+ delete pt ;
92
93
zend_object_std_dtor (object);
93
94
}
94
95
95
96
static zend_object *thread_create_object (zend_class_entry *ce) {
96
97
ThreadObject *to = (ThreadObject *) zend_object_alloc (sizeof (ThreadObject), ce);
97
98
zend_object_std_init (&to->std , ce);
98
99
object_properties_init (&to->std , ce);
100
+ to->pt = new PhpThread ();
99
101
to->std .handlers = &swoole_thread_handlers;
100
102
return &to->std ;
101
103
}
@@ -196,7 +198,7 @@ static PHP_METHOD(swoole_thread, __construct) {
196
198
return ;
197
199
}
198
200
199
- ThreadObject *to = thread_fetch_object ( Z_OBJ_P ( ZEND_THIS) );
201
+ auto pt = thread_get_php_thread ( ZEND_THIS);
200
202
zend_string *file = zend_string_init (script_file, l_script_file, 1 );
201
203
202
204
if (argc > 0 ) {
@@ -207,46 +209,36 @@ static PHP_METHOD(swoole_thread, __construct) {
207
209
}
208
210
209
211
try {
210
- to ->thread = new std::thread ([file, argv]() { php_swoole_thread_start (file, argv); });
212
+ pt ->thread -> start ([file, argv, pt ]() { php_swoole_thread_start (pt-> thread , file, argv); });
211
213
} catch (const std::exception &e) {
212
214
zend_throw_exception (swoole_exception_ce, e.what (), SW_ERROR_SYSTEM_CALL_FAIL);
213
215
return ;
214
216
}
215
217
216
- to->thread_id = to->thread ->native_handle ();
217
- zend::object_set (ZEND_THIS, ZEND_STRL (" id" ), (zend_long) to->thread_id );
218
+ zend::object_set (ZEND_THIS, ZEND_STRL (" id" ), (zend_long) pt->thread ->get_id ());
218
219
}
219
220
220
221
static PHP_METHOD (swoole_thread, isAlive) {
221
- ThreadObject *to = thread_fetch_object ( Z_OBJ_P ( ZEND_THIS) );
222
- RETURN_BOOL (thread_living. get (to-> thread_id ));
222
+ auto pt = thread_get_php_thread ( ZEND_THIS);
223
+ RETURN_BOOL (pt-> thread -> is_alive ( ));
223
224
}
224
225
225
226
static PHP_METHOD (swoole_thread, join) {
226
- ThreadObject *to = thread_fetch_object (Z_OBJ_P (ZEND_THIS));
227
- if (!to || !to->thread || !to->thread ->joinable ()) {
228
- RETURN_FALSE;
229
- }
230
- thread_join (Z_OBJ_P (ZEND_THIS));
231
- RETURN_TRUE;
227
+ auto pt = thread_get_php_thread (ZEND_THIS);
228
+ RETURN_BOOL (pt->join ());
232
229
}
233
230
234
231
static PHP_METHOD (swoole_thread, joinable) {
235
- ThreadObject *to = thread_fetch_object (Z_OBJ_P (ZEND_THIS));
236
- if (to == nullptr || !to->thread ) {
237
- RETURN_FALSE;
238
- }
239
- RETURN_BOOL (to->thread ->joinable ());
232
+ auto pt = thread_get_php_thread (ZEND_THIS);
233
+ RETURN_BOOL (pt->thread ->joinable ());
240
234
}
241
235
242
236
static PHP_METHOD (swoole_thread, detach) {
243
- ThreadObject *to = thread_fetch_object ( Z_OBJ_P ( ZEND_THIS) );
244
- if (to == nullptr || !to ->thread ) {
237
+ auto pt = thread_get_php_thread ( ZEND_THIS);
238
+ if (!pt ->thread -> joinable () ) {
245
239
RETURN_FALSE;
246
240
}
247
- to->thread ->detach ();
248
- delete to->thread ;
249
- to->thread = nullptr ;
241
+ pt->thread ->detach ();
250
242
RETURN_TRUE;
251
243
}
252
244
@@ -261,7 +253,8 @@ static PHP_METHOD(swoole_thread, getId) {
261
253
}
262
254
263
255
static PHP_METHOD (swoole_thread, getExitStatus) {
264
- RETURN_LONG (php_swoole_thread_get_exit_status (thread_get_id (ZEND_THIS)));
256
+ auto pt = thread_get_php_thread (ZEND_THIS);
257
+ RETURN_LONG (pt->thread ->get_exit_status ());
265
258
}
266
259
267
260
static PHP_METHOD (swoole_thread, setName) {
@@ -417,9 +410,9 @@ static void thread_register_stdio_file_handles(bool no_close) {
417
410
zend_register_constant (&ec);
418
411
}
419
412
420
- void php_swoole_thread_start (zend_string *file, ZendArray *argv) {
413
+ void php_swoole_thread_start (std::shared_ptr<Thread> thread, zend_string *file, ZendArray *argv) {
421
414
thread_num.fetch_add (1 );
422
- thread_living. set ( pthread_self (), true );
415
+ thread-> enter ( );
423
416
ts_resource (0 );
424
417
#if defined(COMPILE_DL_SWOOLE) && defined(ZTS)
425
418
ZEND_TSRMLS_CACHE_UPDATE ();
@@ -475,23 +468,13 @@ void php_swoole_thread_start(zend_string *file, ZendArray *argv) {
475
468
file_handle.filename = NULL ;
476
469
477
470
_startup_error:
478
- thread_exit_status.set (pthread_self (), EG (exit_status));
479
-
480
471
zend_string_release (file);
472
+ thread->exit (EG (exit_status));
481
473
ts_free_thread ();
482
474
swoole_thread_clean ();
483
- thread_living.set (pthread_self (), false );
484
475
thread_num.fetch_sub (1 );
485
476
}
486
477
487
- void php_swoole_thread_join (pthread_t ptid) {
488
- thread_exit_status.del (ptid);
489
- }
490
-
491
- int php_swoole_thread_get_exit_status (pthread_t ptid) {
492
- return thread_exit_status.get (ptid);
493
- }
494
-
495
478
size_t sw_active_thread_count (void ) {
496
479
return thread_num.load ();
497
480
}
0 commit comments