aqt_vision_threads.cpp

00001 
00002 /***************************************************************************
00003  *  aqt_vision_threads.cpp - FireVision Base Vision Camera Data
00004  *
00005  *  Created: Mon Sep 24 16:16:25 2007
00006  *  Copyright  2006-2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include <apps/base/aqt_vision_threads.h>
00024 
00025 #include <core/threading/barrier.h>
00026 #include <utils/time/clock.h>
00027 #include <aspect/vision.h>
00028 
00029 #include <algorithm>
00030 
00031 using namespace fawkes;
00032 
00033 /** @class FvAqtVisionThreads <apps/base/aqt_vision_threads.h>
00034  * Aquisition-dependant threads.
00035  * This class is used for managing the vision threads that depend on a
00036  * given aquisition thread. Used internally in base vision.
00037  * @author Tim Niemueller
00038  */
00039 
00040 
00041 /** Constructor.
00042  * @param clock Clock for timeout handling, system time is used only.
00043  */
00044 FvAqtVisionThreads::FvAqtVisionThreads(Clock *clock)
00045 
00046 {
00047   this->clock = clock;
00048 
00049   _empty_time = new Time();
00050   clock->get_systime(_empty_time);
00051 
00052   running_threads_cyclic = new ThreadList();
00053   running_threads_cont = new ThreadList();
00054   waiting_threads = new ThreadList();
00055 
00056   cyclic_barrier = new Barrier(1);
00057 }
00058 
00059 
00060 /** Destructor. */
00061 FvAqtVisionThreads::~FvAqtVisionThreads()
00062 {
00063   delete _empty_time;
00064   delete cyclic_barrier;
00065 
00066   delete running_threads_cyclic;
00067   delete running_threads_cont;
00068   delete waiting_threads;
00069 
00070 }
00071 
00072 
00073 /** Add a thread in waiting state.
00074  * The thread is marked as dependant but it is otherwise ignored.
00075  * @param thread thread to add
00076  * for access to the YUV422_PLANAR image.
00077  */
00078 void
00079 FvAqtVisionThreads::add_waiting_thread(Thread *thread)
00080 {
00081   waiting_threads->push_back_locked(thread);
00082 }
00083 
00084 
00085 /** Mark the thread as running.
00086  * @param thread thread to mark as running
00087  */
00088 void
00089 FvAqtVisionThreads::set_thread_running(Thread *thread)
00090 {
00091   VisionAspect *vision_thread = dynamic_cast<VisionAspect *>(thread);
00092   if ( find(waiting_threads->begin(), waiting_threads->end(), thread) != waiting_threads->end()) {
00093     if ( vision_thread->vision_thread_mode() == VisionAspect::CYCLIC ) {
00094       running_threads_cyclic->push_back_locked(thread);
00095       delete cyclic_barrier;
00096       cyclic_barrier = new Barrier( running_threads_cyclic->size() + 1 );
00097     } else {
00098       running_threads_cont->push_back_locked(thread);
00099     }
00100     waiting_threads->remove_locked(thread);
00101   }
00102 }
00103 
00104 
00105 /** Remove a thread.
00106  * The thread is removed from all internal structures.
00107  * @param thread thread to remove
00108  */
00109 void
00110 FvAqtVisionThreads::remove_thread(Thread *thread)
00111 {
00112   waiting_threads->remove_locked(thread);
00113   if ( find(running_threads_cyclic->begin(), running_threads_cyclic->end(), thread) !=
00114        running_threads_cyclic->end()) {
00115 
00116     running_threads_cyclic->remove_locked(thread);
00117 
00118     delete cyclic_barrier;
00119     cyclic_barrier = new Barrier( running_threads_cyclic->size() + 1 );
00120   }
00121   running_threads_cont->remove_locked(thread);
00122   if ( empty() ) {
00123     clock->get_systime(_empty_time);
00124   }
00125 }
00126 
00127 
00128 /** Remove waiting thread.
00129  * @param thread thread to remove from waiting structures.
00130  */
00131 void
00132 FvAqtVisionThreads::remove_waiting_thread(Thread *thread)
00133 {
00134   waiting_threads->remove_locked(thread);
00135   if ( empty() ) {
00136     clock->get_systime(_empty_time);
00137   }
00138 }
00139 
00140 
00141 /** Check if there is at least one cyclic thread.
00142  * @return true if there is at least one cyclic thread, false otherwise.
00143  */
00144 bool
00145 FvAqtVisionThreads::has_cyclic_thread()
00146 {
00147   return ( ! running_threads_cyclic->empty() );
00148 }
00149 
00150 
00151 /** Check if the given waiting thread is registered.
00152  * @param t thread to check for
00153  * @return true if the given thread is marked as waiting, false otherwise
00154  */
00155 bool
00156 FvAqtVisionThreads::has_waiting_thread(Thread *t)
00157 {
00158   return (find(waiting_threads->begin(), waiting_threads->end(), t) != waiting_threads->end());
00159 }
00160 
00161 
00162 /** Check if there is no thread at all.
00163  * @return true if there is no thread in any of the internal running or waiting
00164  * lists, false otherwise
00165  */
00166 bool
00167 FvAqtVisionThreads::empty()
00168 {
00169   return ( waiting_threads->empty() &&
00170            running_threads_cyclic->empty() &&
00171            running_threads_cont->empty() );
00172 }
00173 
00174 
00175 /** Get the empty time.
00176  * @return the time in seconds since the last thread has been removed.
00177  */
00178 float
00179 FvAqtVisionThreads::empty_time()
00180 {
00181   return clock->elapsed(_empty_time);
00182 }
00183 
00184 
00185 /** Wakeup and wait for all cyclic threads. */
00186 void
00187 FvAqtVisionThreads::wakeup_and_wait_cyclic_threads()
00188 {
00189   if ( has_cyclic_thread() ) {
00190     running_threads_cyclic->wakeup(cyclic_barrier);
00191     cyclic_barrier->wait();
00192   }
00193 }
00194 
00195 
00196 /** Set prepfin hold fo cyclic threads.
00197  * Sets prepfin hold for cyclice threads and rolls back if it cannot
00198  * be set for any of the threads.
00199  * @param hold prepfin hold value
00200  * @exception Exception thrown if setting fails
00201  * @see Thread::set_prepfin_hold()
00202  * @see ThreadList::set_prepfin_hold()
00203  */
00204 void
00205 FvAqtVisionThreads::set_prepfin_hold(bool hold)
00206 {
00207   try {
00208     running_threads_cyclic->set_prepfin_hold(hold);
00209   } catch (Exception &e) {
00210     running_threads_cyclic->set_prepfin_hold(false);
00211     throw;
00212   }
00213 }