History

misc: add a thread pool

To be used by the following commits.

wm4 committed 9 years ago

Commit ec3dd711 parent 7bab24b2 files · +135 −0Browse files

Unified · Split

2 files
  1. misc/thread_pool.c +125 −0
  2. misc/thread_pool.h +10 −0
misc/thread_pool.c+125−0
@@ -0,0 +1,125 @@
1/*
2 * This file is part of mpv.
3 *
4 * mpv is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * mpv is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <pthread.h>
19
20#include "common/common.h"
21
22#include "thread_pool.h"
23
24struct work {
25 void (*fn)(void *ctx);
26 void *fn_ctx;
27};
28
29struct mp_thread_pool {
30 pthread_t *threads;
31 int num_threads;
32
33 pthread_mutex_t lock;
34 pthread_cond_t wakeup;
35
36 // --- the following fields are protected by lock
37 bool terminate;
38 struct work *work;
39 int num_work;
40};
41
42static void *worker_thread(void *arg)
43{
44 struct mp_thread_pool *pool = arg;
45
46 pthread_mutex_lock(&pool->lock);
47 while (1) {
48 while (!pool->num_work && !pool->terminate)
49 pthread_cond_wait(&pool->wakeup, &pool->lock);
50
51 if (!pool->num_work && pool->terminate)
52 break;
53
54 assert(pool->num_work > 0);
55 struct work work = pool->work[pool->num_work - 1];
56 pool->num_work -= 1;
57
58 pthread_mutex_unlock(&pool->lock);
59 work.fn(work.fn_ctx);
60 pthread_mutex_lock(&pool->lock);
61 }
62 assert(pool->num_work == 0);
63 pthread_mutex_unlock(&pool->lock);
64
65 return NULL;
66}
67
68static void thread_pool_dtor(void *ctx)
69{
70 struct mp_thread_pool *pool = ctx;
71
72 pthread_mutex_lock(&pool->lock);
73 pool->terminate = true;
74 pthread_cond_broadcast(&pool->wakeup);
75 pthread_mutex_unlock(&pool->lock);
76
77 for (int n = 0; n < pool->num_threads; n++)
78 pthread_join(pool->threads[n], NULL);
79
80 assert(pool->num_work == 0);
81 pthread_cond_destroy(&pool->wakeup);
82 pthread_mutex_destroy(&pool->lock);
83}
84
85// Create a thread pool with the given number of worker threads. This can return
86// NULL if the worker threads could not be created. The thread pool can be
87// destroyed with talloc_free(pool), or indirectly with talloc_free(ta_parent).
88// If there are still work items on freeing, it will block until all work items
89// are done, and the threads terminate.
90struct mp_thread_pool *mp_thread_pool_create(void *ta_parent, int threads)
91{
92 assert(threads > 0);
93
94 struct mp_thread_pool *pool = talloc_zero(ta_parent, struct mp_thread_pool);
95 talloc_set_destructor(pool, thread_pool_dtor);
96
97 pthread_mutex_init(&pool->lock, NULL);
98 pthread_cond_init(&pool->wakeup, NULL);
99
100 for (int n = 0; n < threads; n++) {
101 pthread_t thread;
102 if (pthread_create(&thread, NULL, worker_thread, pool)) {
103 talloc_free(pool);
104 return NULL;
105 }
106 MP_TARRAY_APPEND(pool, pool->threads, pool->num_threads, thread);
107 }
108
109 return pool;
110}
111
112// Queue a function to be run on a worker thread: fn(fn_ctx)
113// If no worker thread is currently available, it's appended to a list in memory
114// with unbounded size. This function always returns immediately.
115// Concurrent queue calls are allowed, as long as it does not overlap with
116// pool destruction.
117void mp_thread_pool_queue(struct mp_thread_pool *pool, void (*fn)(void *ctx),
118 void *fn_ctx)
119{
120 pthread_mutex_lock(&pool->lock);
121 struct work work = {fn, fn_ctx};
122 MP_TARRAY_INSERT_AT(pool, pool->work, pool->num_work, 0, work);
123 pthread_cond_signal(&pool->wakeup);
124 pthread_mutex_unlock(&pool->lock);
125}
misc/thread_pool.h+10−0
@@ -0,0 +1,10 @@
1#ifndef MPV_MP_THREAD_POOL_H
2#define MPV_MP_THREAD_POOL_H
3
4struct mp_thread_pool;
5
6struct mp_thread_pool *mp_thread_pool_create(void *ta_parent, int threads);
7void mp_thread_pool_queue(struct mp_thread_pool *pool, void (*fn)(void *ctx),
8 void *fn_ctx);
9
10#endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t