2525#include < unordered_map>
2626#include < atomic>
2727
28- #include " swoole_thread.h"
29-
3028BEGIN_EXTERN_C ()
3129#include " stubs/php_swoole_thread_arginfo.h"
3230END_EXTERN_C ()
@@ -45,11 +43,24 @@ static struct {
4543
4644TSRMLS_CACHE_EXTERN ();
4745
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+ };
4961
5062struct ThreadObject {
51- Thread *thread;
52- pthread_t thread_id;
63+ PhpThread *pt;
5364 zend_object std;
5465};
5566
@@ -58,44 +69,35 @@ static void thread_register_stdio_file_handles(bool no_close);
5869static thread_local zval thread_argv = {};
5970static thread_local JMP_BUF *thread_bailout = nullptr ;
6071static 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 );
6372
6473static sw_inline ThreadObject *thread_fetch_object (zend_object *obj) {
6574 return (ThreadObject *) ((char *) obj - swoole_thread_handlers.offset );
6675}
6776
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));
7279}
7380
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 ;
7683}
7784
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 ;
8687}
8788
8889static 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 ;
9293 zend_object_std_dtor (object);
9394}
9495
9596static zend_object *thread_create_object (zend_class_entry *ce) {
9697 ThreadObject *to = (ThreadObject *) zend_object_alloc (sizeof (ThreadObject), ce);
9798 zend_object_std_init (&to->std , ce);
9899 object_properties_init (&to->std , ce);
100+ to->pt = new PhpThread ();
99101 to->std .handlers = &swoole_thread_handlers;
100102 return &to->std ;
101103}
@@ -196,7 +198,7 @@ static PHP_METHOD(swoole_thread, __construct) {
196198 return ;
197199 }
198200
199- ThreadObject *to = thread_fetch_object ( Z_OBJ_P ( ZEND_THIS) );
201+ auto pt = thread_get_php_thread ( ZEND_THIS);
200202 zend_string *file = zend_string_init (script_file, l_script_file, 1 );
201203
202204 if (argc > 0 ) {
@@ -207,46 +209,36 @@ static PHP_METHOD(swoole_thread, __construct) {
207209 }
208210
209211 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); });
211213 } catch (const std::exception &e) {
212214 zend_throw_exception (swoole_exception_ce, e.what (), SW_ERROR_SYSTEM_CALL_FAIL);
213215 return ;
214216 }
215217
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 ());
218219}
219220
220221static 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 ( ));
223224}
224225
225226static 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 ());
232229}
233230
234231static 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 ());
240234}
241235
242236static 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 () ) {
245239 RETURN_FALSE;
246240 }
247- to->thread ->detach ();
248- delete to->thread ;
249- to->thread = nullptr ;
241+ pt->thread ->detach ();
250242 RETURN_TRUE;
251243}
252244
@@ -261,7 +253,8 @@ static PHP_METHOD(swoole_thread, getId) {
261253}
262254
263255static 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 ());
265258}
266259
267260static PHP_METHOD (swoole_thread, setName) {
@@ -417,9 +410,9 @@ static void thread_register_stdio_file_handles(bool no_close) {
417410 zend_register_constant (&ec);
418411}
419412
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) {
421414 thread_num.fetch_add (1 );
422- thread_living. set ( pthread_self (), true );
415+ thread-> enter ( );
423416 ts_resource (0 );
424417#if defined(COMPILE_DL_SWOOLE) && defined(ZTS)
425418 ZEND_TSRMLS_CACHE_UPDATE ();
@@ -475,23 +468,13 @@ void php_swoole_thread_start(zend_string *file, ZendArray *argv) {
475468 file_handle.filename = NULL ;
476469
477470_startup_error:
478- thread_exit_status.set (pthread_self (), EG (exit_status));
479-
480471 zend_string_release (file);
472+ thread->exit (EG (exit_status));
481473 ts_free_thread ();
482474 swoole_thread_clean ();
483- thread_living.set (pthread_self (), false );
484475 thread_num.fetch_sub (1 );
485476}
486477
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-
495478size_t sw_active_thread_count (void ) {
496479 return thread_num.load ();
497480}
0 commit comments