00001 /*!@file Component/ModelParam.C A tunable ModelComponent parameter base class */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Component/ModelParam.C $ 00035 // $Id: ModelParam.C 8746 2007-09-05 23:17:08Z rjpeters $ 00036 // 00037 00038 #include "Component/ModelParam.H" 00039 00040 #include "Component/ModelOptionDef.H" 00041 #include "Component/ParamClient.H" 00042 #include "Component/ParamMap.H" 00043 #include "Util/Assert.H" 00044 #include "Util/log.H" 00045 #include "rutz/demangle.h" 00046 00047 #include <ostream> 00048 00049 namespace 00050 { 00051 void initMutex(pthread_mutex_t* mut, int type) 00052 { 00053 pthread_mutexattr_t attr; 00054 if (0 != pthread_mutexattr_init(&attr)) 00055 PLFATAL("pthread_mutexattr_init() failed"); 00056 00057 if (0 != pthread_mutexattr_settype(&attr, type)) 00058 { 00059 pthread_mutexattr_destroy(&attr); 00060 PLFATAL("pthread_mutexattr_settype() failed"); 00061 } 00062 00063 if (0 != pthread_mutex_init(mut, &attr)) 00064 { 00065 pthread_mutexattr_destroy(&attr); 00066 PLFATAL("pthread_mutex_init() failed"); 00067 } 00068 00069 if (0 != pthread_mutexattr_destroy(&attr)) 00070 PLERROR("pthread_mutexattr_destroy() failed"); 00071 } 00072 } 00073 00074 // ###################################################################### 00075 // ############# ModelParamAuxImpl implementation 00076 // ###################################################################### 00077 00078 // ###################################################################### 00079 ModelParamAuxImpl::ModelParamAuxImpl(OptionedModelParam* self, 00080 const ModelOptionDef* def, 00081 ParamClient* client, 00082 const int flags, 00083 const std::type_info& valtype) 00084 : 00085 itsSelf(self), 00086 itsClient(client), 00087 itsOption(def), 00088 itsName(def->name), 00089 itsLocks(itsSelf->allowsOnlineChanges() ? new pthread_mutex_t[2] : 0), 00090 itsInCallback(false) 00091 { 00092 ASSERT(itsSelf != 0); 00093 ASSERT(itsClient != 0); 00094 ASSERT(itsOption != 0); 00095 00096 if (itsLocks != 0) 00097 { 00098 initMutex(&itsLocks[READLOCK], PTHREAD_MUTEX_RECURSIVE); 00099 initMutex(&itsLocks[WRITELOCK], PTHREAD_MUTEX_ERRORCHECK); 00100 } 00101 00102 // register ourselves with our master: 00103 itsClient->registerOptionedParam(self, flags); 00104 00105 if (def->type.argtype == 0) 00106 LFATAL("ModelOptionDef '%s' had a null argtype type_info", 00107 def->name); 00108 00109 if (*def->type.argtype != valtype) 00110 LFATAL("the ModelParam '%s' " 00111 "being registered by '%s' has type '%s', " 00112 "but the corresponding ModelOptionDef has type '%s'", 00113 def->name, 00114 rutz::demangled_name(typeid(*client)), 00115 rutz::demangled_name(valtype), 00116 rutz::demangled_name(*def->type.argtype)); 00117 } 00118 00119 // ###################################################################### 00120 ModelParamAuxImpl::ModelParamAuxImpl(ModelParamBase* self, 00121 const std::string& nam, 00122 ParamClient* client) 00123 : 00124 itsSelf(self), 00125 itsClient(client), 00126 itsOption(0), 00127 itsName(nam), 00128 itsLocks(itsSelf->allowsOnlineChanges() ? new pthread_mutex_t[2] : 0), 00129 itsInCallback(false) 00130 { 00131 ASSERT(itsSelf != 0); 00132 ASSERT(itsClient != 0); 00133 00134 if (itsLocks != 0) 00135 { 00136 initMutex(&itsLocks[READLOCK], PTHREAD_MUTEX_RECURSIVE); 00137 initMutex(&itsLocks[WRITELOCK], PTHREAD_MUTEX_ERRORCHECK); 00138 } 00139 00140 // register ourselves with our master: 00141 itsClient->registerParam(itsSelf); 00142 } 00143 00144 // ###################################################################### 00145 ModelParamAuxImpl::~ModelParamAuxImpl() 00146 { 00147 ASSERT(itsClient != 0); 00148 00149 // un-register ourselves with our master: 00150 itsClient->unregisterParam(itsSelf); 00151 00152 if (itsLocks != 0) 00153 { 00154 if (0 != pthread_mutex_destroy(&itsLocks[READLOCK])) 00155 PLERROR("pthread_mutex_destroy() failed for read lock"); 00156 if (0 != pthread_mutex_destroy(&itsLocks[WRITELOCK])) 00157 PLERROR("pthread_mutex_destroy() failed for write lock"); 00158 delete [] itsLocks; 00159 } 00160 } 00161 00162 // ###################################################################### 00163 std::string ModelParamAuxImpl::getName() const 00164 { 00165 ASSERT(itsClient != 0); 00166 00167 return itsName; 00168 } 00169 00170 // ###################################################################### 00171 const ModelOptionDef* ModelParamAuxImpl::getOptionDef() const 00172 { 00173 ASSERT(itsClient != 0); 00174 00175 ASSERT(itsOption != 0); 00176 00177 return itsOption; 00178 } 00179 00180 // ###################################################################### 00181 void ModelParamAuxImpl::printout(std::ostream& s, const std::string& prefix) const 00182 { 00183 ASSERT(itsClient != 0); 00184 00185 s<<prefix<<": "<<itsName<<" = "<<itsSelf->getValString()<<std::endl; 00186 } 00187 00188 // ###################################################################### 00189 void ModelParamAuxImpl::writeTo(ParamMap& pmap) const 00190 { 00191 ASSERT(itsClient != 0); 00192 00193 pmap.putStringParam(itsName, itsSelf->getValString()); 00194 } 00195 00196 // ###################################################################### 00197 void ModelParamAuxImpl::readFrom(const ParamMap& pmap, const bool noerr) 00198 { 00199 ASSERT(itsClient != 0); 00200 00201 std::string res = itsSelf->getValString(); 00202 ParamMap::ReturnCode rc = pmap.queryStringParam(itsName, res); 00203 if (rc == ParamMap::CHANGED) 00204 // will cause a paramChanged() to be sent to our client 00205 itsSelf->setValString(res); 00206 00207 if (noerr == false && rc == ParamMap::MISSING) 00208 LERROR("Cannot find parameter %s in ParamMap", itsName.c_str()); 00209 } 00210 00211 // ###################################################################### 00212 ParamClient::ChangeStatus 00213 ModelParamAuxImpl::sendChangedMessage(bool didchange) 00214 { 00215 if (itsInCallback) 00216 LFATAL("Oops! Got a re-entrant paramChanged() call for '%s' -- " 00217 "make sure you aren't re-setting %s from within its own " 00218 "paramChanged() callback, either directly with setVal(), " 00219 "or indirectly via exportOptions() or something similar", 00220 itsName.c_str(), itsName.c_str()); 00221 00222 itsInCallback = true; 00223 ParamClient::ChangeStatus status = ParamClient::CHANGE_ACCEPTED; 00224 try { 00225 itsClient->paramChanged(itsSelf, didchange, &status); 00226 } catch (...) { 00227 itsInCallback = false; 00228 throw; 00229 } 00230 itsInCallback = false; 00231 return status; 00232 } 00233 00234 // ###################################################################### 00235 const char* ModelParamAuxImpl::defaultValueOf(const ModelOptionDef* def) 00236 { 00237 return def->defval; 00238 } 00239 00240 // ###################################################################### 00241 /* So things look consistent in everyone's emacs... */ 00242 /* Local Variables: */ 00243 /* indent-tabs-mode: nil */ 00244 /* End: */