pelib  2.0.0
src/schedule.cpp
Go to the documentation of this file.
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