Libbarrett
1.2.4
|
00001 /* 00002 Copyright 2009, 2010 Barrett Technology <support@barrett.com> 00003 00004 This file is part of libbarrett. 00005 00006 This version of libbarrett is free software: you can redistribute it 00007 and/or modify it under the terms of the GNU General Public License as 00008 published by the Free Software Foundation, either version 3 of the 00009 License, or (at your option) any later version. 00010 00011 This version of libbarrett is distributed in the hope that it will be 00012 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License along 00017 with this version of libbarrett. If not, see 00018 <http://www.gnu.org/licenses/>. 00019 00020 Further, non-binding information about licensing is available at: 00021 <http://wiki.barrett.com/libbarrett/wiki/LicenseNotes> 00022 */ 00023 00024 /* 00025 * converter-inl.h 00026 * 00027 * Created on: Oct 29, 2009 00028 * Author: dc 00029 */ 00030 00031 #include <utility> 00032 #include <list> 00033 #include <stdexcept> 00034 #include <cassert> 00035 00036 #include <barrett/detail/stl_utils.h> 00037 #include <barrett/systems/abstract/system.h> 00038 #include <barrett/systems/helpers.h> 00039 #include <barrett/systems/abstract/conversion.h> 00040 00041 00042 // I think RTTI is useful here to keep syntax clean and support flexibility and 00043 // extensibility. Also, Visitor and multiple-dispatch don't really fit in this 00044 // usage. 00045 // FIXME(dc): Is there a clean way to get this behavior without RTTI? 00046 00047 namespace barrett { 00048 namespace systems { 00049 00050 00051 template<typename OutputType> 00052 inline Converter<OutputType>::~Converter() 00053 { 00054 mandatoryCleanUp(); 00055 barrett::detail::purge(conversions); 00056 } 00057 00058 template<typename OutputType> 00059 inline void Converter<OutputType>::registerConversion( 00060 Conversion<OutputType>* conversion) 00061 { 00062 conversions.push_front(conversion); 00063 } 00064 00065 template<typename OutputType> 00066 template<typename T> 00067 void Converter<OutputType>::connectInputTo( 00068 System::Output<T>& output) 00069 throw(std::invalid_argument) 00070 { 00071 if ( !connectInputToNoThrow(output) ) { 00072 throw std::invalid_argument( 00073 "(systems::Converter::connectInputTo): No systems::Conversion " 00074 "is registered that matches the output's type."); 00075 } 00076 } 00077 00078 template<typename OutputType> 00079 template<typename T> 00080 bool Converter<OutputType>::connectInputToNoThrow(System::Output<T>& output) 00081 { 00082 System::Input<T>* input = NULL; 00083 Conversion<OutputType>* conversion = getInput(&input); 00084 if (input == NULL) { 00085 return false; 00086 } 00087 00088 { 00089 // Make sure these two steps happen at the same time in case input is 00090 // already connected to something else. 00091 BARRETT_SCOPED_LOCK(input->getEmMutex()); 00092 00093 this->outputValue->delegateTo(conversion->getConversionOutput()); 00094 forceConnect(output, *input); 00095 } 00096 00097 return true; 00098 } 00099 00100 template<typename OutputType> 00101 template<typename T> 00102 Conversion<OutputType>* Converter<OutputType>::getInput(System::Input<T>** input) 00103 { 00104 typename std::list<Conversion<OutputType>*>::iterator i; 00105 for (i = conversions.begin(); i != conversions.end(); ++i) { 00106 Conversion<OutputType>* conversion = *i; 00107 *input = dynamic_cast<System::Input<T>*>( //NOLINT: see RTTI note above 00108 conversion->getConversionInput() ); 00109 00110 if (*input != NULL) { 00111 return conversion; 00112 } 00113 } 00114 00115 assert(*input == NULL); 00116 return NULL; 00117 } 00118 00119 template<typename OutputType> 00120 void Converter<OutputType>::disconnectInput() 00121 { 00122 this->outputValue->undelegate(); 00123 } 00124 00125 00126 } 00127 }