]>
Commit | Line | Data |
---|---|---|
adca27eb JH |
1 | /** |
2 | * @file job_queue.c | |
79538669 | 3 | * |
d048df5c | 4 | * @brief Implementation of job_queue_t |
79538669 | 5 | * |
adca27eb JH |
6 | */ |
7 | ||
8 | /* | |
9 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | */ | |
22 | ||
954d34e3 | 23 | #include <stdlib.h> |
adca27eb | 24 | #include <pthread.h> |
79538669 | 25 | |
adca27eb | 26 | #include "job_queue.h" |
b85d20d1 | 27 | |
8080fccb | 28 | #include <utils/linked_list.h> |
adca27eb | 29 | |
95c61cb9 JH |
30 | |
31 | typedef struct private_job_queue_t private_job_queue_t; | |
32 | ||
adca27eb JH |
33 | /** |
34 | * @brief Private Variables and Functions of job_queue class | |
79538669 | 35 | * |
adca27eb | 36 | */ |
95c61cb9 | 37 | struct private_job_queue_t { |
a6cbf648 MW |
38 | |
39 | /** | |
40 | * public members | |
41 | */ | |
adca27eb | 42 | job_queue_t public; |
79538669 | 43 | |
adca27eb JH |
44 | /** |
45 | * The jobs are stored in a linked list | |
46 | */ | |
47 | linked_list_t *list; | |
a6cbf648 | 48 | |
adca27eb JH |
49 | /** |
50 | * access to linked_list is locked through this mutex | |
51 | */ | |
52 | pthread_mutex_t mutex; | |
79538669 | 53 | |
adca27eb JH |
54 | /** |
55 | * If the queue is empty a thread has to wait | |
56 | * This condvar is used to wake up such a thread | |
57 | */ | |
79538669 | 58 | pthread_cond_t condvar; |
adca27eb JH |
59 | }; |
60 | ||
61 | ||
62 | /** | |
d048df5c | 63 | * implements job_queue_t.get_count |
adca27eb | 64 | */ |
1061c878 | 65 | static int get_count(private_job_queue_t *this) |
adca27eb | 66 | { |
1061c878 | 67 | int count; |
adca27eb | 68 | pthread_mutex_lock(&(this->mutex)); |
1061c878 | 69 | count = this->list->get_count(this->list); |
adca27eb | 70 | pthread_mutex_unlock(&(this->mutex)); |
1061c878 | 71 | return count; |
adca27eb JH |
72 | } |
73 | ||
74 | /** | |
d048df5c | 75 | * implements job_queue_t.get |
adca27eb | 76 | */ |
d048df5c | 77 | static job_t *get(private_job_queue_t *this) |
adca27eb | 78 | { |
db5dc986 | 79 | int oldstate; |
d048df5c | 80 | job_t *job; |
adca27eb | 81 | pthread_mutex_lock(&(this->mutex)); |
db5dc986 | 82 | /* go to wait while no jobs available */ |
1061c878 | 83 | while(this->list->get_count(this->list) == 0) |
adca27eb | 84 | { |
db5dc986 MW |
85 | /* add mutex unlock handler for cancellation, enable cancellation */ |
86 | pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); | |
87 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); | |
79538669 | 88 | |
adca27eb | 89 | pthread_cond_wait( &(this->condvar), &(this->mutex)); |
79538669 | 90 | |
db5dc986 MW |
91 | /* reset cancellation, remove mutex-unlock handler (without executing) */ |
92 | pthread_setcancelstate(oldstate, NULL); | |
93 | pthread_cleanup_pop(0); | |
adca27eb | 94 | } |
d048df5c | 95 | this->list->remove_first(this->list,(void **) &job); |
adca27eb | 96 | pthread_mutex_unlock(&(this->mutex)); |
d048df5c | 97 | return job; |
adca27eb JH |
98 | } |
99 | ||
100 | /** | |
d048df5c | 101 | * implements function job_queue_t.add |
adca27eb | 102 | */ |
d048df5c | 103 | static void add(private_job_queue_t *this, job_t *job) |
adca27eb | 104 | { |
adca27eb JH |
105 | pthread_mutex_lock(&(this->mutex)); |
106 | this->list->insert_last(this->list,job); | |
107 | pthread_cond_signal( &(this->condvar)); | |
108 | pthread_mutex_unlock(&(this->mutex)); | |
adca27eb JH |
109 | } |
110 | ||
111 | /** | |
d048df5c | 112 | * implements job_queue_t.destroy |
adca27eb | 113 | */ |
d048df5c | 114 | static void job_queue_destroy (private_job_queue_t *this) |
79538669 | 115 | { |
1061c878 | 116 | while (this->list->get_count(this->list) > 0) |
adca27eb JH |
117 | { |
118 | job_t *job; | |
119 | if (this->list->remove_first(this->list,(void *) &job) != SUCCESS) | |
120 | { | |
121 | this->list->destroy(this->list); | |
122 | break; | |
123 | } | |
8b3bc23b | 124 | job->destroy_all(job); |
adca27eb JH |
125 | } |
126 | this->list->destroy(this->list); | |
79538669 | 127 | |
adca27eb | 128 | pthread_mutex_destroy(&(this->mutex)); |
79538669 | 129 | |
adca27eb | 130 | pthread_cond_destroy(&(this->condvar)); |
79538669 | 131 | |
5113680f | 132 | free(this); |
adca27eb JH |
133 | } |
134 | ||
135 | /* | |
79538669 | 136 | * |
adca27eb JH |
137 | * Documented in header |
138 | */ | |
139 | job_queue_t *job_queue_create() | |
140 | { | |
5113680f | 141 | private_job_queue_t *this = malloc_thing(private_job_queue_t); |
79538669 | 142 | |
1061c878 | 143 | this->public.get_count = (int(*)(job_queue_t*))get_count; |
d048df5c MW |
144 | this->public.get = (job_t*(*)(job_queue_t*))get; |
145 | this->public.add = (void(*)(job_queue_t*, job_t*))add; | |
146 | this->public.destroy = (void(*)(job_queue_t*))job_queue_destroy; | |
79538669 | 147 | |
d048df5c | 148 | this->list = linked_list_create(); |
adca27eb JH |
149 | pthread_mutex_init(&(this->mutex), NULL); |
150 | pthread_cond_init(&(this->condvar), NULL); | |
79538669 | 151 | |
adca27eb JH |
152 | return (&this->public); |
153 | } |