WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / taskset.c
blob285db16387927c7cc35134e5f8a9bf7e6399d00e
1 /* taskset.c
3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
10 #include "hb.h"
11 #include "ports.h"
12 #include "taskset.h"
14 int
15 taskset_init( taskset_t *ts, int thread_count, size_t arg_size )
17 int init_step;
19 init_step = 0;
20 memset( ts, 0, sizeof( *ts ) );
21 ts->thread_count = thread_count;
22 ts->arg_size = arg_size;
23 ts->bitmap_elements = ( ts->thread_count + 31 ) / 32;
24 ts->task_threads = malloc( sizeof( hb_thread_t* ) * ts->thread_count );
25 if( ts->task_threads == NULL )
26 goto fail;
27 init_step++;
29 if( arg_size != 0 )
31 ts->task_threads_args = malloc( arg_size * ts->thread_count );
32 if( ts->task_threads == NULL )
33 goto fail;
35 init_step++;
37 ts->task_begin_bitmap = malloc( sizeof( uint32_t ) * ts->bitmap_elements );
38 if( ts->task_begin_bitmap == NULL )
39 goto fail;
40 init_step++;
42 ts->task_complete_bitmap = malloc( sizeof( uint32_t ) * ts->bitmap_elements );
43 if( ts->task_complete_bitmap == NULL )
44 goto fail;
45 init_step++;
47 ts->task_stop_bitmap = malloc( sizeof( uint32_t ) * ts->bitmap_elements );
48 if( ts->task_stop_bitmap == NULL )
49 goto fail;
50 init_step++;
52 ts->task_cond_lock = hb_lock_init();
53 if( ts->task_cond_lock == NULL)
54 goto fail;
55 init_step++;
57 ts->task_begin = hb_cond_init();
58 if( ts->task_begin == NULL)
59 goto fail;
60 init_step++;
62 ts->task_complete = hb_cond_init();
63 if( ts->task_complete == NULL)
64 goto fail;
65 init_step++;
68 * Initialize all arg data to 0.
70 memset(ts->task_threads_args, 0, ts->arg_size * ts->thread_count );
73 * Inialize bitmaps to all bits set. This means that any unused bits
74 * in the bitmap are already in the "condition satisfied" state allowing
75 * us to test the bitmap 32bits at a time without having to mask off
76 * the end.
78 memset(ts->task_begin_bitmap, 0xFF, sizeof( uint32_t ) * ts->bitmap_elements );
79 memset(ts->task_complete_bitmap, 0xFF, sizeof( uint32_t ) * ts->bitmap_elements );
80 memset(ts->task_stop_bitmap, 0, sizeof( uint32_t ) * ts->bitmap_elements );
83 * Important to start off with the threads locked waiting
84 * on input, no work completed, and not asked to stop.
86 bit_nclear( ts->task_begin_bitmap, 0, ts->thread_count - 1 );
87 bit_nclear( ts->task_complete_bitmap, 0, ts->thread_count - 1 );
88 bit_nclear( ts->task_stop_bitmap, 0, ts->thread_count - 1 );
89 return (1);
91 fail:
92 switch (init_step)
94 default:
95 hb_cond_close( &ts->task_complete );
96 /* FALL THROUGH */
97 case 7:
98 hb_cond_close( &ts->task_begin );
99 /* FALL THROUGH */
100 case 6:
101 hb_lock_close( &ts->task_cond_lock );
102 /* FALL THROUGH */
103 case 5:
104 free( ts->task_stop_bitmap );
105 /* FALL THROUGH */
106 case 4:
107 free( ts->task_complete_bitmap );
108 /* FALL THROUGH */
109 case 3:
110 free( ts->task_begin_bitmap );
111 /* FALL THROUGH */
112 case 2:
113 if( ts->task_threads_args == NULL )
114 free( ts->task_threads_args );
115 /* FALL THROUGH */
116 case 1:
117 free( ts->task_threads );
118 /* FALL THROUGH */
119 case 0:
120 break;
122 return (0);
126 taskset_thread_spawn( taskset_t *ts, int thr_idx, const char *descr,
127 thread_func_t *func, int priority )
129 ts->task_threads[thr_idx] = hb_thread_init( descr, func,
130 taskset_thread_args( ts, thr_idx ),
131 priority);
132 return( ts->task_threads[thr_idx] != NULL );
135 void
136 taskset_cycle( taskset_t *ts )
138 hb_lock( ts->task_cond_lock );
141 * Signal all threads that their work is available.
143 bit_nset( ts->task_begin_bitmap, 0, ts->thread_count - 1 );
144 hb_cond_broadcast( ts->task_begin );
147 * Wait until all threads have completed. Note that we must
148 * loop here as hb_cond_wait() on some platforms (e.g pthead_cond_wait)
149 * may unblock prematurely.
153 hb_cond_wait( ts->task_complete, ts->task_cond_lock );
154 } while ( !allbits_set( ts->task_complete_bitmap, ts->bitmap_elements ) );
157 * Clear completion indications for next time.
159 bit_nclear( ts->task_complete_bitmap, 0, ts->thread_count - 1 );
161 hb_unlock( ts->task_cond_lock );
165 * Block current thread until work is available for it.
167 void
168 taskset_thread_wait4start( taskset_t *ts, int thr_idx )
170 hb_lock( ts->task_cond_lock );
171 while ( bit_is_clear( ts->task_begin_bitmap, thr_idx ) )
172 hb_cond_wait( ts->task_begin, ts->task_cond_lock );
175 * We've been released for one run. Insure we block the next
176 * time through the loop.
178 bit_clear( ts->task_begin_bitmap, thr_idx );
179 hb_unlock( ts->task_cond_lock );
183 * Current thread has completed its work. Indicate completion,
184 * and if all threads in this task set have completed, wakeup
185 * anyone waiting for this condition.
187 void
188 taskset_thread_complete( taskset_t *ts, int thr_idx )
190 hb_lock( ts->task_cond_lock );
191 bit_set( ts->task_complete_bitmap, thr_idx );
192 if( allbits_set( ts->task_complete_bitmap, ts->bitmap_elements ) )
194 hb_cond_signal( ts->task_complete );
196 hb_unlock( ts->task_cond_lock );
199 void
200 taskset_fini( taskset_t *ts )
202 int i;
204 hb_lock( ts->task_cond_lock );
206 * Tell each thread to stop, and then cleanup.
208 bit_nset( ts->task_stop_bitmap, 0, ts->thread_count - 1 );
209 bit_nset( ts->task_begin_bitmap, 0, ts->thread_count - 1 );
210 hb_cond_broadcast( ts->task_begin );
213 * Wait for all threads to exit.
215 hb_cond_wait( ts->task_complete, ts->task_cond_lock );
216 hb_unlock( ts->task_cond_lock );
219 * Clean up taskset memory.
221 for( i = 0; i < ts->thread_count; i++)
223 hb_thread_close( &ts->task_threads[i] );
225 hb_lock_close( &ts->task_cond_lock );
226 hb_cond_close( &ts->task_begin );
227 hb_cond_close( &ts->task_complete );
228 free( ts->task_threads );
229 if( ts->task_threads_args != NULL )
230 free( ts->task_threads_args );
231 free( ts->task_begin_bitmap );
232 free( ts->task_complete_bitmap );
233 free( ts->task_stop_bitmap );