Skip to content

Commit 59d652a

Browse files
authored
Refactor impl of Thread::getExitStatus()/Thread::isAlive() (#5695)
* Refactor impl of thread exit_code/living --filter=[thread] * fix --filter=[thread] * optimize code * optimize code [2]
1 parent d647b78 commit 59d652a

10 files changed

+137
-125
lines changed

ext-src/php_swoole_thread.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
#include "php_swoole_cxx.h"
2121

2222
#ifdef SW_THREAD
23-
24-
#include "swoole_lock.h"
23+
#include "swoole_thread.h"
2524

2625
typedef uint32_t ThreadResourceId;
2726
class ThreadResource;
@@ -37,9 +36,7 @@ extern zend_class_entry *swoole_thread_lock_ce;
3736
extern zend_class_entry *swoole_thread_map_ce;
3837
extern zend_class_entry *swoole_thread_queue_ce;
3938

40-
void php_swoole_thread_start(zend_string *file, ZendArray *argv);
41-
void php_swoole_thread_join(pthread_t ptid);
42-
int php_swoole_thread_get_exit_status(pthread_t ptid);
39+
void php_swoole_thread_start(std::shared_ptr<swoole::Thread> thread, zend_string *file, ZendArray *argv);
4340
void php_swoole_thread_bailout(void);
4441

4542
ThreadResource *php_swoole_thread_arraylist_cast(zval *zobject);

ext-src/swoole_server.cc

+2-8
Original file line numberDiff line numberDiff line change
@@ -2684,21 +2684,15 @@ static PHP_METHOD(swoole_server, start) {
26842684
zval_ptr_dtor(&_thread_argv);
26852685
}
26862686

2687-
serv->worker_thread_start = [bootstrap, thread_argv](const WorkerFn &fn) {
2687+
serv->worker_thread_start = [bootstrap, thread_argv](std::shared_ptr<Thread> thread, const WorkerFn &fn) {
26882688
worker_thread_fn = fn;
26892689
zend_string *bootstrap_copy = zend_string_dup(bootstrap, 1);
26902690
if (thread_argv) {
26912691
thread_argv->add_ref();
26922692
}
2693-
php_swoole_thread_start(bootstrap_copy, thread_argv);
2693+
php_swoole_thread_start(thread, bootstrap_copy, thread_argv);
26942694
};
26952695

2696-
serv->worker_thread_get_exit_status = [](pthread_t ptid) -> int {
2697-
return php_swoole_thread_get_exit_status(ptid);
2698-
};
2699-
2700-
serv->worker_thread_join = [](pthread_t ptid) { php_swoole_thread_join(ptid); };
2701-
27022696
/**
27032697
*The hook must be enabled before creating child threads.
27042698
*The stream factory and ops are global variables, not thread-local resources.

ext-src/swoole_thread.cc

+43-60
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525
#include <unordered_map>
2626
#include <atomic>
2727

28-
#include "swoole_thread.h"
29-
3028
BEGIN_EXTERN_C()
3129
#include "stubs/php_swoole_thread_arginfo.h"
3230
END_EXTERN_C()
@@ -45,11 +43,24 @@ static struct {
4543

4644
TSRMLS_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

5062
struct 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);
5869
static thread_local zval thread_argv = {};
5970
static thread_local JMP_BUF *thread_bailout = nullptr;
6071
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);
6372

6473
static 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

8889
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;
9293
zend_object_std_dtor(object);
9394
}
9495

9596
static 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

220221
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());
223224
}
224225

225226
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());
232229
}
233230

234231
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());
240234
}
241235

242236
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()) {
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

263255
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());
265258
}
266259

267260
static 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-
495478
size_t sw_active_thread_count(void) {
496479
return thread_num.load();
497480
}

include/swoole_api.h

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ SW_API bool swoole_timer_clear(long timer_id);
4343
SW_API void swoole_timer_free();
4444
SW_API int swoole_timer_select();
4545
SW_API bool swoole_timer_is_available();
46+
SW_API void swoole_timer_set_scheduler(const swoole::TimerScheduler &scheduler);
4647

4748
SW_API int swoole_event_init(int flags);
4849
SW_API int swoole_event_add(swoole::network::Socket *socket, int events);

include/swoole_server.h

+3-10
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@
2727
#include "swoole_pipe.h"
2828
#include "swoole_channel.h"
2929
#include "swoole_message_bus.h"
30-
#ifdef SW_THREAD
31-
#include "swoole_lock.h"
32-
#endif
3330

3431
#ifdef SW_USE_OPENSSL
3532
#include "swoole_dtls.h"
@@ -57,6 +54,7 @@ struct Request;
5754

5855
class Server;
5956
struct Manager;
57+
class Thread;
6058

6159
typedef std::function<void(void)> WorkerFn;
6260

@@ -450,17 +448,14 @@ class ProcessFactory : public Factory {
450448

451449
class ThreadFactory : public BaseFactory {
452450
private:
453-
std::vector<std::thread> threads_;
451+
std::vector<std::shared_ptr<Thread>> threads_;
454452
std::mutex lock_;
455453
std::condition_variable cv_;
456454
std::queue<Worker *> queue_;
457455
long cv_timeout_ms_;
458456
bool reload_all_workers;
459457
bool reloading;
460458
Worker manager;
461-
template <typename _Callable>
462-
void create_thread(int i, _Callable fn);
463-
void join_thread(std::thread &thread);
464459
void at_thread_exit(Worker *worker);
465460
void create_message_bus();
466461
void destroy_message_bus();
@@ -1489,9 +1484,7 @@ class Server {
14891484
void worker_accept_event(DataHead *info);
14901485
void worker_signal_init(void);
14911486

1492-
std::function<void(const WorkerFn &fn)> worker_thread_start;
1493-
std::function<void(pthread_t ptid)> worker_thread_join;
1494-
std::function<int(pthread_t ptid)> worker_thread_get_exit_status;
1487+
std::function<void(std::shared_ptr<Thread>, const WorkerFn &fn)> worker_thread_start;
14951488

14961489
/**
14971490
* [Master]

include/swoole_thread.h

+49
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,52 @@ static bool swoole_thread_set_name(const char *name) {
6262
return pthread_setname_np(pthread_self(), name) == 0;
6363
#endif
6464
}
65+
66+
namespace swoole {
67+
class Thread {
68+
private:
69+
int exit_status;
70+
bool living;
71+
std::thread thread;
72+
73+
public:
74+
bool is_alive() {
75+
return living;
76+
}
77+
78+
bool joinable() {
79+
return thread.joinable();
80+
}
81+
82+
void join() {
83+
thread.join();
84+
}
85+
86+
void detach() {
87+
thread.detach();
88+
}
89+
90+
int get_exit_status() {
91+
return exit_status;
92+
}
93+
94+
pthread_t get_id() {
95+
return thread.native_handle();
96+
}
97+
98+
template <typename _Callable>
99+
void start(_Callable fn) {
100+
thread = std::thread(fn);
101+
}
102+
103+
void enter() {
104+
exit_status = 0;
105+
living = true;
106+
}
107+
108+
void exit(int status) {
109+
exit_status = status;
110+
living = false;
111+
}
112+
};
113+
} // namespace swoole

0 commit comments

Comments
 (0)