/***************************************************************************** * Copyright (c) 2008, University of Florida * All rights reserved. * * This file is part of OpenJAUS. OpenJAUS is distributed under the BSD * license. See the LICENSE file for details. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the University of Florida nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ****************************************************************************/ // File Name: LocalComponent.cpp // // Written By: Danny Kent (jaus AT dannykent DOT com) // // Version: 3.3.0a // // Date: 08/07/08 // // Description: Defines the common fuctionality of local components. // Used by the NodeManagerComponent and CommunicatorComponent classes. #include "nodeManager/LocalComponent.h" #include "utils/timeval.h" void LocalComponent::run() { struct timespec timeout; struct timeval now; if(!this->cmpt) { // ERROR: This cannot be called if we haven't yet constructed our component // TODO: Throw an exception? Log an error. return; } this->startupState(); this->cmpt->state = JAUS_INITIALIZE_STATE; // Lock our mutex pthread_mutex_lock(&this->threadMutex); // prepare new timeout value. // Note that we need an absolute time. gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec; // timeval uses micro-seconds. // timespec uses nano-seconds. // 1 micro-second = 1000 nano-seconds. timeout.tv_nsec = (now.tv_usec * 1000) + (long)(1e9 / this->cmptRateHz); while(this->running) { while(timeout.tv_nsec > 1e9) { timeout.tv_nsec -= (long)1e9; timeout.tv_sec++; } int rc = pthread_cond_timedwait(&this->threadConditional, &this->threadMutex, &timeout); switch(rc) { case 0: // Conditional Signal // Check the send queue while(!this->queue.isEmpty()) { // Pop a packet off the queue and send it off processMessage(queue.pop()); // Check if we need to run our state thread! gettimeofday(&now, NULL); if( now.tv_sec > timeout.tv_sec || (now.tv_usec*1000) > timeout.tv_nsec) { break; } } break; case ETIMEDOUT: // our time is up // Capture time now, that way we get a constant deltaTime from beginning to beginning gettimeofday(&now, NULL); switch(cmpt->state) { case JAUS_INITIALIZE_STATE: intializeState(); break; case JAUS_STANDBY_STATE: standbyState(); break; case JAUS_READY_STATE: readyState(); break; case JAUS_EMERGENCY_STATE: emergencyState(); break; case JAUS_FAILURE_STATE: failureState(); break; default: //do nothing break; } allState(); // prepare new timeout value. // Note that we need an absolute time. timeout.tv_sec = now.tv_sec; // timeval uses micro-seconds. // timespec uses nano-seconds. // 1 micro-second = 1000 nano-seconds. timeout.tv_nsec = (now.tv_usec * 1000) + (long)(1e9 / this->cmptRateHz); while(!this->queue.isEmpty()) { // Pop a packet off the queue and send it off processMessage(queue.pop()); // Check if we need to run our state thread! gettimeofday(&now, NULL); if( now.tv_sec > timeout.tv_sec || (now.tv_usec*1000) > timeout.tv_nsec) { break; } } break; default: // Some other error occured // TODO: Log error. gettimeofday(&now, NULL); // prepare new timeout value. // Note that we need an absolute time. timeout.tv_sec = now.tv_sec; // timeval uses micro-seconds. // timespec uses nano-seconds. // 1 micro-second = 1000 nano-seconds. timeout.tv_nsec = (now.tv_usec * 1000) + (long)(1e9 / this->cmptRateHz); break; } } while(!this->queue.isEmpty()) { // Pop a packet off the queue and send it off processMessage(queue.pop()); } pthread_mutex_unlock(&this->threadMutex); shutdownState(); }