source: geovis/trunk/ResponseQueue.cpp @ 6369

Last change on this file since 6369 was 5930, checked in by ldelgass, 8 years ago

Add stub for select features protocol command.

File size: 3.4 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2013  HUBzero Foundation, LLC
4 *
5 * Author: George A. Howlett <gah@purdue.edu>
6 */
7
8#include <pthread.h>
9#include <semaphore.h>
10#include <cerrno>
11#include <cstring>
12#include <cstdlib>
13#include <list>
14
15#include "Trace.h"
16#include "ResponseQueue.h"
17
18using namespace GeoVis;
19
20ResponseQueue::ResponseQueue()
21{
22    pthread_mutex_init(&_idle, NULL);
23    if (sem_init(&_ready, 0, 0) < 0) {
24        ERROR("can't initialize semaphore: %s", strerror(errno));
25    }
26}
27
28ResponseQueue::~ResponseQueue()
29{
30    TRACE("Deleting ResponseQueue");
31    pthread_mutex_destroy(&_idle);
32    if (sem_destroy(&_ready) < 0) {
33        ERROR("can't destroy semaphore: %s", strerror(errno));
34    }
35    for (std::list<Response *>::iterator itr = _list.begin();
36         itr != _list.end(); ++itr) {
37        delete *itr;
38    }
39    _list.clear();
40}
41
42void
43ResponseQueue::enqueue(Response *response)
44{
45    if (pthread_mutex_lock(&_idle) != 0) {
46        ERROR("can't lock mutex: %s", strerror(errno));
47    }
48#ifdef QUEUE_ONLY_ONE_FRAME
49    /* Examine the list and remove any queued responses of the same type. */
50#ifdef TRACE_RESPONSE_QUEUE
51    TRACE("Before # of elements is %d", _list.size());
52#endif
53    for (std::list<Response *>::iterator itr = _list.begin();
54         itr != _list.end();) {
55        /* Remove any duplicate image or legend responses. There should be no
56         * more than one.  Note that if the client starts using multiple legends
57         * for different fields, this optimization should be disabled for legends.
58         * We may also need to differentiate between screen images and "hardcopy"
59         * images.
60         */
61        if ((response->type() == Response::IMAGE ||
62             response->type() == Response::LEGEND) &&
63            (*itr)->type() == response->type()) {
64            TRACE("Removing duplicate response of type: %d", (*itr)->type());
65            delete *itr;
66            itr = _list.erase(itr);
67        } else {
68#ifdef TRACE_RESPONSE_QUEUE
69            TRACE("Found queued response of type %d", (*itr)->type());
70#endif
71            ++itr;
72        }
73    }
74#endif
75    /* Add the new response to the end of the list. */
76    _list.push_back(response);
77#ifdef TRACE_RESPONSE_QUEUE
78    TRACE("After # of elements is %d", _list.size());
79#endif
80    if (sem_post(&_ready) < 0) {
81        ERROR("can't post semaphore: %s", strerror(errno));
82    }
83    if (pthread_mutex_unlock(&_idle) != 0) {
84        ERROR("can't unlock mutex: %s", strerror(errno));
85    }
86}
87
88Response *
89ResponseQueue::dequeue()
90{
91    Response *response = NULL;
92
93    int ret;
94    while ((ret = sem_wait(&_ready)) < 0 && errno == EINTR)
95        continue;
96    if (ret < 0) {
97        ERROR("can't wait on semaphore: %s", strerror(errno));
98    }
99    if (pthread_mutex_lock(&_idle) != 0) {
100        ERROR("can't lock mutex: %s", strerror(errno));
101    }
102    /* List may be empty if semaphore value was incremented beyond list
103     * size in the case of an enqueue operation deleting from the queue
104     * This is not an error, so just unlock and return to wait loop
105     */
106    if (_list.empty()) {
107        TRACE("Empty queue");
108    } else {
109        response = _list.front();
110        _list.pop_front();
111#ifdef TRACE_RESPONSE_QUEUE
112        TRACE("Dequeued response of type %d", response->type());
113#endif
114    }
115    if (pthread_mutex_unlock(&_idle) != 0) {
116        ERROR("can't unlock mutex: %s", strerror(errno));
117    }
118    return response;
119}
Note: See TracBrowser for help on using the repository browser.