IIINSTRUMENT Pipeline Reference Manual 4.6.1
visir_queue.c
1/* $Id: visir_queue.c,v 1.4 2012-10-24 14:57:42 jtaylor Exp $
2 *
3 * This file is part of the VISIR Pipeline
4 * Copyright (C) 2012 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: jtaylor $
23 * $Date: 2012-10-24 14:57:42 $
24 * $Revision: 1.4 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#if defined _OPENMP && _OPENMP >= 200805
32
33/*-----------------------------------------------------------------------------
34 Includes
35 -----------------------------------------------------------------------------*/
36
37#include <cxlist.h>
38#include <cpl.h>
39#include <time.h>
40#include <omp.h>
41
42/*-----------------------------------------------------------------------------
43 Define
44 -----------------------------------------------------------------------------*/
45
46/*----------------------------------------------------------------------------*/
51/*----------------------------------------------------------------------------*/
52
53
54typedef struct {
55 int max_size;
56 int size;
57 cpl_error_code error;
58 cx_list * queue;
59 omp_lock_t lock;
60} visir_queue;
61
62
63/*----------------------------------------------------------------------------*/
69/*----------------------------------------------------------------------------*/
70visir_queue * visir_queue_init(const int max_size)
71{
72 visir_queue * q = cpl_malloc(sizeof(visir_queue));
73 q->max_size = max_size <= 0 ? INT_MAX : max_size;
74 q->size = 0;
75 q->error = CPL_ERROR_NONE;
76 q->queue = cx_list_new();
77 omp_init_lock(&(q->lock));
78 return q;
79}
80
81
82/*----------------------------------------------------------------------------*/
87/*----------------------------------------------------------------------------*/
88void visir_queue_delete(visir_queue * q)
89{
90 cx_list_delete(q->queue);
91 omp_destroy_lock(&(q->lock));
92 cpl_free(q);
93}
94
95
96/*----------------------------------------------------------------------------*/
102/*----------------------------------------------------------------------------*/
103void visir_queue_set_error(visir_queue * q, cpl_error_code error)
104{
105 omp_set_lock(&(q->lock));
106 q->error = error;
107 omp_unset_lock(&(q->lock));
108}
109
110
111/*----------------------------------------------------------------------------*/
122/*----------------------------------------------------------------------------*/
123cpl_error_code visir_queue_put(visir_queue * q, void * data)
124{
125 /* double checked lock failures not so bad here */
126#pragma omp flush
127 while (q->size >= q->max_size && q->error == CPL_ERROR_NONE) {
128 /* no condition variables in omp :( */
129 struct timespec ts = { 0, 50 * 1000000 };
130 nanosleep(&ts, NULL);
131#pragma omp taskyield
132#pragma omp flush
133 }
134
135 omp_set_lock(&(q->lock));
136 if (q->size >= q->max_size || q->error != CPL_ERROR_NONE) {
137 omp_unset_lock(&(q->lock));
138 return q->error;
139 }
140 cx_list_push_back(q->queue, data);
141 q->size++;
142 omp_unset_lock(&(q->lock));
143
144 return CPL_ERROR_NONE;
145}
146
147
148/*----------------------------------------------------------------------------*/
158/*----------------------------------------------------------------------------*/
159void * visir_queue_pop(visir_queue * q)
160{
161 void * data = NULL;
162
163 while (1) {
164 omp_set_lock(&(q->lock));
165 if (q->size > 0 && q->error == CPL_ERROR_NONE) {
166 data = cx_list_pop_front(q->queue);
167 q->size--;
168 omp_unset_lock(&(q->lock));
169 break;
170 }
171 else {
172 omp_unset_lock(&(q->lock));
173 /* no condition variables in omp :( */
174 struct timespec ts;
175 ts.tv_sec = 0;
176 ts.tv_nsec = 50 * 1000000;
177 if (q->error != CPL_ERROR_NONE)
178 return NULL;
179 nanosleep(&ts, NULL);
180#pragma omp taskyield
181 }
182 }
183 return data;
184}
185
186#endif