pelib
2.0.0
|
00001 /* 00002 Copyright 2015 Nicolas Melot 00003 00004 This file is part of Pelib. 00005 00006 Pelib is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 Pelib is distributed in the hope that it will be useful, 00012 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 00017 along with Pelib. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 00021 #include <iostream> 00022 #include <cstdlib> 00023 #include <vector> 00024 #include <map> 00025 00026 #include <pelib/AmplInput.hpp> 00027 #include <pelib/Taskgraph.hpp> 00028 #include <pelib/Platform.hpp> 00029 #include <pelib/Schedule.hpp> 00030 00031 #include <pelib/XMLSchedule.hpp> 00032 00033 #include <pelib/process.h> 00034 #include <pelib/argument_parsing.hpp> 00035 #include <pelib/dl.h> 00036 00037 #ifdef debug 00038 #undef debug 00039 #endif 00040 00041 #define debug(expr) cerr << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #expr << " = \"" << expr << "\"." << endl; 00042 00043 using namespace std; 00044 using namespace pelib; 00045 00046 #ifdef __cplusplus 00047 extern "C" { 00048 #endif 00049 00050 struct args 00051 { 00052 bool showStatsOut; 00053 bool showStatsErr; 00054 bool showDescription; 00055 char* showStatsFile; 00056 pelib_argument_stream lib; 00057 }; 00058 typedef struct args args_t; 00059 00060 static 00061 args_t 00062 parse(char** arg) 00063 { 00064 args_t args; 00065 args.showStatsOut = false; 00066 args.showStatsErr = false; 00067 args.showStatsFile = NULL; 00068 args.showDescription = false; 00069 pelib_argument_stream_init(&args.lib); 00070 00071 for(; arg[0] != NULL && string(arg[0]).compare("--") != 0; arg++) 00072 { 00073 if(strcmp(arg[0], "--show-stats") == 0) 00074 { 00075 arg++; 00076 00077 if(strcmp(arg[0], "--stdout") == 0) 00078 { 00079 args.showStatsOut = true; 00080 } 00081 else if(strcmp(arg[0], "--stderr") == 0) 00082 { 00083 args.showStatsErr = true; 00084 } 00085 else 00086 { 00087 args.showStatsFile = arg[0]; 00088 } 00089 continue; 00090 } 00091 if(strcmp(arg[0], "--description") == 0) 00092 { 00093 args.showDescription = true; 00094 continue; 00095 } 00096 00097 // Nothing else, try to parse a library 00098 arg += pelib_argument_stream_parse(arg, &args.lib) - 1; 00099 continue; 00100 } 00101 00102 return args; 00103 } 00104 00105 // TODO: find a way to use libdl to invoke the library that created the object 00106 char *library; 00107 00108 std::map<const char*, pelib::Record*> 00109 pelib_process(std::map<const char*, pelib::Record*> records, size_t argc, char** argv) 00110 { 00111 // Parse extra arguments and skip them 00112 args_t args = parse(argv); 00113 00114 if(args.lib.library == NULL) 00115 { 00116 cerr << "[ERROR] No scheduler specified. Aborting" << endl; 00117 return map<const char*, Record*>(); 00118 } 00119 00120 // Load library 00121 library = args.lib.library; 00122 void *libScheduler = load_lib(library); 00123 map<const char*, Record*> output; 00124 00125 if(!args.showDescription) 00126 { 00127 Schedule* (*schedule)(const Taskgraph &tg, const Platform &pt, size_t argc, char **argv, map<const string, double> &statistics) = (Schedule* (*)(const Taskgraph &tg, const Platform &pt, size_t argc, char **argv, map<const string, double> &statistics))load_function(libScheduler, "pelib_schedule"); 00128 00129 // Read input data 00130 if(records.find(typeid(Taskgraph).name()) != records.end() && records.find(typeid(Platform).name()) != records.end()) 00131 { 00132 Taskgraph *tg = (Taskgraph*)records.find(typeid(Taskgraph).name())->second; 00133 if(tg == NULL) 00134 { 00135 cerr << "[ERROR] Missing taskgraph description. Aborting" << endl; 00136 return map<const char*, Record*>(); 00137 } 00138 Platform *pt = (Platform*)records.find(typeid(Platform).name())->second; 00139 if(pt == NULL) 00140 { 00141 cerr << "[ERROR] Missing platform description. Aborting" << endl; 00142 return map<const char*, Record*>(); 00143 } 00144 00145 // Prepare output collection and fill it with schedule generated by library 00146 map<const string, double> statistics; 00147 Schedule *sched = schedule(*tg, *pt, args.lib.argc, args.lib.argv, statistics); 00148 //Schedule *sched = new Schedule("Dummy", "Dummy", Schedule::table()); 00149 Taskgraph *ptg = new Taskgraph(tg); 00150 Platform *ppt = new Platform(pt); 00151 output.insert(pair<const char*, Record*>(typeid(Schedule).name(), sched)); 00152 output.insert(pair<const char*, Record*>(typeid(Taskgraph).name(), ptg)); 00153 output.insert(pair<const char*, Record*>(typeid(Platform).name(), ppt)); 00154 00155 // Show solving statistics 00156 if(args.showStatsFile != NULL) 00157 { 00158 ofstream statsFileStr(args.showStatsFile); 00159 for(map<const string, double>::iterator i = statistics.begin(); i != statistics.end(); i++) 00160 { 00161 statsFileStr << i->first << " = " << i->second << endl; 00162 } 00163 statsFileStr.close(); 00164 } 00165 else if(args.showStatsOut || args.showStatsErr) 00166 { 00167 for(map<const string, double>::iterator i = statistics.begin(); i != statistics.end(); i++) 00168 { 00169 if(args.showStatsOut) 00170 { 00171 cout << i->first << " = " << i->second << endl; 00172 } 00173 else 00174 { 00175 cerr << i->first << " = " << i->second << endl; 00176 } 00177 } 00178 } 00179 } 00180 } 00181 else 00182 { 00183 string (*description)(size_t argc, char **argv) = (string (*)(size_t argc, char **argv))load_function(libScheduler, "pelib_description"); 00184 cout << description(args.lib.argc, args.lib.argv) << endl; 00185 } 00186 00187 destroy_lib(libScheduler); 00188 00189 return output; 00190 } 00191 00192 void 00193 pelib_delete(pelib::Record* obj) 00194 { 00195 void *libScheduler = load_lib(library); 00196 void (*del)(const Schedule*) = (void (*)(const Schedule*))load_function(libScheduler, "pelib_delete"); 00197 00198 if(string(typeid(Schedule).name()).compare(typeid(*obj).name()) == 0) 00199 { 00200 del((Schedule*)obj); 00201 } 00202 else 00203 { 00204 delete obj; 00205 } 00206 } 00207 00208 #ifdef __cplusplus 00209 } 00210 #endif 00211