VISIR Pipeline Reference Manual  4.1.0
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 
54 typedef 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 /*----------------------------------------------------------------------------*/
70 visir_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 /*----------------------------------------------------------------------------*/
88 void 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 /*----------------------------------------------------------------------------*/
103 void 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 /*----------------------------------------------------------------------------*/
123 cpl_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 /*----------------------------------------------------------------------------*/
159 void * 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