• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aremmell / libsir / 473

06 Sep 2023 02:24AM UTC coverage: 94.751% (+0.1%) from 94.608%
473

Pull #258

gitlab-ci

johnsonjh
Merge branch 'set-thread-names' of github.com:/aremmell/libsir into set-thread-names
Pull Request #258: Bug fix, new tests, portable set thread name functionality

473 of 473 new or added lines in 10 files covered. (100.0%)

3105 of 3277 relevant lines covered (94.75%)

614386.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.88
/src/sirthreadpool.c
1
/*
2
 * sirthreadpool.c
3
 *
4
 * Author:    Ryan M. Lederman <lederman@gmail.com>
5
 * Copyright: Copyright (c) 2018-2023
6
 * Version:   2.2.3
7
 * License:   The MIT License (MIT)
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
10
 * this software and associated documentation files (the "Software"), to deal in
11
 * the Software without restriction, including without limitation the rights to
12
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13
 * the Software, and to permit persons to whom the Software is furnished to do so,
14
 * subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
#include "sir/condition.h"
27
#include "sir/threadpool.h"
28
#include "sir/internal.h"
29
#include "sir/queue.h"
30
#include "sir/mutex.h"
31

32
#if !defined(__WIN__)
33
static void* thread_pool_proc(void* arg);
34
#else
35
static unsigned __stdcall thread_pool_proc(void* arg);
36
#endif
37

38
bool _sir_threadpool_create(sir_threadpool** pool, size_t num_threads) {
21✔
39
    if (!pool || !num_threads)
21✔
40
        return false;
×
41

42
    *pool = calloc(1, sizeof(sir_threadpool));
21✔
43
    if (!*pool) {
21✔
44
        _sir_handleerr(errno);
×
45
        return false;
×
46
    }
47

48
    (*pool)->threads = calloc(num_threads, sizeof(sir_thread));
21✔
49
    if (!(*pool)->threads) {
21✔
50
        _sir_handleerr(errno);
×
51
        _sir_threadpool_destroy(pool);
×
52
        return false;
×
53
    }
54

55
    (*pool)->num_threads = num_threads;
21✔
56

57
    if (!_sir_queue_create(&(*pool)->jobs) || !_sir_condcreate(&(*pool)->cond) ||
24✔
58
        !_sir_mutexcreate(&(*pool)->mutex)) {
21✔
59
            _sir_threadpool_destroy(pool);
×
60
            return false;
×
61
    }
62

63
    for (size_t n = 0; n < num_threads; n++) {
105✔
64
#if !defined(__WIN__)
65
        pthread_attr_t attr;
66
        pthread_attr_init(&attr);
84✔
67
        int op = pthread_create(&(*pool)->threads[n], &attr, &thread_pool_proc, *pool);
84✔
68
        if (0 != op) {
84✔
69
            (*pool)->threads[n] = 0;
×
70
            _sir_handleerr(op);
×
71
            _sir_threadpool_destroy(pool);
×
72
            return false;
×
73
        }
74

75
#else /* __WIN__ */
76
        (*pool)->threads[n] = (HANDLE)_beginthreadex(NULL, 0, &thread_pool_proc,
77
            *pool, 0, NULL);
78
        if (!(*pool)->threads[n]) {
79
            _sir_handleerr(errno);
80
            _sir_threadpool_destroy(pool);
81
            return false;
82
        }
83
#endif
84
    }
85

86
    return !!*pool;
21✔
87
}
88

89
bool _sir_threadpool_add_job(sir_threadpool* pool, sir_threadpool_job* job) {
601✔
90
    bool retval = false;
511✔
91

92
    if (pool && pool->jobs && job && job->fn && job->data) {
601✔
93
        bool locked = _sir_mutexlock(&pool->mutex);
601✔
94
        SIR_ASSERT(locked);
571✔
95

96
        if (locked) {
541✔
97
            if (_sir_queue_push(pool->jobs, job)) {
601✔
98
                retval = _sir_condbroadcast(&pool->cond);
601✔
99
                _sir_selflog("added job; new size: %zu", _sir_queue_size(pool->jobs));
601✔
100
            }
101

102
            bool unlocked = _sir_mutexunlock(&pool->mutex);
601✔
103
            SIR_ASSERT_UNUSED(unlocked, unlocked);
571✔
104
        }
105
    }
106

107
    return retval;
601✔
108
}
109

110
bool _sir_threadpool_destroy(sir_threadpool** pool) {
20✔
111
    if (!pool || !*pool)
20✔
112
        return false;
×
113

114
    bool locked = _sir_mutexlock(&(*pool)->mutex);
20✔
115
    SIR_ASSERT(locked);
19✔
116

117
    if (locked) {
18✔
118
        _sir_selflog("broadcasting signal to condition var...");
19✔
119
        (*pool)->cancel = true;
20✔
120

121
        bool bcast = _sir_condbroadcast(&(*pool)->cond);
20✔
122
        SIR_ASSERT_UNUSED(bcast, bcast);
19✔
123

124
        bool unlock = _sir_mutexunlock(&(*pool)->mutex);
20✔
125
        SIR_ASSERT_UNUSED(unlock, unlock);
19✔
126
    }
127

128
    for (size_t n = 0; n < (*pool)->num_threads; n++) {
100✔
129
        if ((*pool)->threads[n]) {
80✔
130
            _sir_selflog("joining thread %zu of %zu...", n + 1, (*pool)->num_threads);
76✔
131
#if !defined(__WIN__)
132
            int join = pthread_join((*pool)->threads[n], NULL);
80✔
133
            SIR_ASSERT_UNUSED(0 == join, join);
76✔
134
#else /* __WIN__ */
135
            DWORD join = WaitForSingleObject((*pool)->threads[n], INFINITE);
136
            SIR_ASSERT_UNUSED(WAIT_OBJECT_0 == join, join);
137
#endif
138
        }
139
    }
140

141
    bool destroy = _sir_queue_destroy(&(*pool)->jobs);
20✔
142
    SIR_ASSERT_UNUSED(destroy, destroy);
19✔
143

144
    destroy = _sir_conddestroy(&(*pool)->cond);
20✔
145
    SIR_ASSERT_UNUSED(destroy, destroy);
19✔
146

147
    destroy = _sir_mutexdestroy(&(*pool)->mutex);
20✔
148
    SIR_ASSERT_UNUSED(destroy, destroy);
19✔
149

150
    _sir_safefree(&(*pool)->threads);
20✔
151
    _sir_safefree(pool);
20✔
152

153
    return true;
20✔
154
}
155

156
#if !defined(__WIN__)
157
static void* thread_pool_proc(void* arg)
84✔
158
#else
159
static unsigned __stdcall thread_pool_proc(void* arg)
160
#endif
161
{
162
    sir_threadpool* pool = (sir_threadpool*)arg;
72✔
163
    while (true) {
142✔
164
        bool locked = _sir_mutexlock(&pool->mutex);
226✔
165
        SIR_ASSERT_UNUSED(locked, locked);
222✔
166

167
        while (_sir_queue_isempty(pool->jobs) && !pool->cancel) {
335✔
168
#if !defined(__WIN__)
169
            /* seconds; absolute fixed time. */
170
            sir_wait wait = {time(NULL) + 2, 0};
106✔
171
#else
172
            /* msec; relative from now. */
173
            sir_wait wait = 2000;
174
#endif
175
            (void)_sir_condwait_timeout(&pool->cond, &pool->mutex, &wait);
106✔
176
        }
177

178
        if (!pool->cancel) {
229✔
179
            sir_threadpool_job* job = NULL;
149✔
180
            bool job_popped         = _sir_queue_pop(pool->jobs, (void**)&job);
149✔
181

182
            bool unlocked = _sir_mutexunlock(&pool->mutex);
149✔
183
            SIR_ASSERT_UNUSED(unlocked, unlocked);
142✔
184

185
            if (job_popped) {
149✔
186
                _sir_selflog("picked up job (fn: %"PRIxPTR", data: %p)",
149✔
187
                    (uintptr_t)job->fn, job->data);
188
                job->fn(job->data);
149✔
189
                _sir_safefree(&job);
149✔
190
            }
191
        } else {
192
            _sir_selflog("cancel flag is set; exiting");
76✔
193
            bool unlocked = _sir_mutexunlock(&pool->mutex);
80✔
194
            SIR_ASSERT_UNUSED(unlocked, unlocked);
76✔
195
            break;
68✔
196
        }
197
    }
198

199
#if !defined(__WIN__)
200
    return NULL;
80✔
201
#else /* __WIN__ */
202
    return 0U;
203
#endif
204
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc