source: geovis/trunk/ResponseQueue.cpp @ 4635

Last change on this file since 4635 was 4629, checked in by ldelgass, 10 years ago

add token to map/screen coord commands

File size: 3.3 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    TRACE("Before # of elements is %d", _list.size());
51    for (std::list<Response *>::iterator itr = _list.begin();
52         itr != _list.end();) {
53        /* Remove any duplicate image or legend responses. There should be no
54         * more than one.  Note that if the client starts using multiple legends
55         * for different fields, this optimization should be disabled for legends.
56         * We may also need to differentiate between screen images and "hardcopy"
57         * images.
58         */
59        if ((response->type() == Response::IMAGE ||
60             response->type() == Response::LEGEND) &&
61            (*itr)->type() == response->type()) {
62            TRACE("Removing duplicate response of type: %d", (*itr)->type());
63            delete *itr;
64            itr = _list.erase(itr);
65        } else {
66            TRACE("Found queued response of type %d", (*itr)->type());
67            ++itr;
68        }
69    }
70#endif
71    /* Add the new response to the end of the list. */
72    _list.push_back(response);
73    TRACE("After # of elements is %d", _list.size());
74    if (sem_post(&_ready) < 0) {
75        ERROR("can't post semaphore: %s", strerror(errno));
76    }
77    if (pthread_mutex_unlock(&_idle) != 0) {
78        ERROR("can't unlock mutex: %s", strerror(errno));
79    }
80}
81
82Response *
83ResponseQueue::dequeue()
84{
85    Response *response = NULL;
86
87    int ret;
88    while ((ret = sem_wait(&_ready)) < 0 && errno == EINTR)
89        continue;
90    if (ret < 0) {
91        ERROR("can't wait on semaphore: %s", strerror(errno));
92    }
93    if (pthread_mutex_lock(&_idle) != 0) {
94        ERROR("can't lock mutex: %s", strerror(errno));
95    }
96    /* List may be empty if semaphore value was incremented beyond list
97     * size in the case of an enqueue operation deleting from the queue
98     * This is not an error, so just unlock and return to wait loop
99     */
100    if (_list.empty()) {
101        TRACE("Empty queue");
102    } else {
103        response = _list.front();
104        _list.pop_front();
105        TRACE("Dequeued response of type %d", response->type());
106    }
107    if (pthread_mutex_unlock(&_idle) != 0) {
108        ERROR("can't unlock mutex: %s", strerror(errno));
109    }
110    return response;
111}
Note: See TracBrowser for help on using the repository browser.