00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <UT/UT_DSOVersion.h>
00029 #include <UT/UT_WritePipe.h>
00030 #include <FS/FS_EventGenerator.h>
00031 #include <CMD/CMD_Args.h>
00032 #include <CMD/CMD_Manager.h>
00033
00034
00035
00036 namespace HDK_Sample {
00037
00038
00039
00040
00041
00042
00043
00044 class BackgroundTask {
00045 public:
00046 BackgroundTask() : myPipe(NULL) {}
00047 ~BackgroundTask() { close(); }
00048
00049
00050
00051
00052
00053 FILE *open(const char *cmd, char *text=0, int length=0)
00054 {
00055 FILE *fp;
00056
00057 myCommand.harden(cmd);
00058 if (myPipe)
00059 close();
00060 myPipe = new UT_WritePipe();
00061 fp = myPipe->open(cmd);
00062 if (fp && text && length > 0)
00063 {
00064
00065
00066
00067
00068 if (fwrite(text, 1, length, fp) != length)
00069 {
00070 close();
00071 fp = NULL;
00072 }
00073 else
00074 fflush(fp);
00075 }
00076 return fp;
00077 }
00078
00079
00080 void close()
00081 {
00082 if (myPipe)
00083 {
00084 myPipe->close(true);
00085 delete myPipe;
00086 myPipe = NULL;
00087 }
00088 }
00089
00090
00091 bool isComplete()
00092 {
00093 return !myPipe || myPipe->isComplete(false);
00094 }
00095
00096 UT_String myCommand;
00097 UT_WritePipe *myPipe;
00098 };
00099
00100 static UT_PtrArray<BackgroundTask *> theTasks;
00101
00102 static void
00103 pollTasks()
00104 {
00105 int i;
00106 #if defined(DEMO_DEBUG)
00107 fprintf(stderr, "Poll: %d\n", theTasks.entries());
00108 #endif
00109 for (i = 0; i < theTasks.entries(); ++i)
00110 {
00111 if (theTasks(i)->isComplete())
00112 {
00113 #if defined(DEMO_DEBUG)
00114 if (theTasks(i)->myPipe)
00115 fprintf(stderr, "Delete [%d] %s\n",
00116 theTasks(i)->myPipe->getPid(),
00117 (const char *)theTasks(i)->myCommand);
00118 #endif
00119 delete theTasks(i);
00120 theTasks(i) = 0;
00121 }
00122 }
00123 theTasks.collapse();
00124 }
00125
00126
00127 static void
00128 listTasks(ostream &os)
00129 {
00130 int i;
00131 os << theTasks.entries() << " background tasks\n";
00132 for (i = 0; i < theTasks.entries(); i++)
00133 {
00134 if (theTasks(i)->myPipe)
00135 {
00136 os << i
00137 << " pid[" << theTasks(i)->myPipe->getPid()
00138 << "] " << theTasks(i)->myCommand
00139 << endl;
00140 }
00141 }
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151 class BackgroundTimer : public FS_EventGenerator {
00152 public:
00153 BackgroundTimer() {}
00154 virtual ~BackgroundTimer() {}
00155
00156 virtual const char *getClassName() const { return "BackgroundTimer"; }
00157
00158
00159 virtual int getPollTime() { return 500; }
00160
00161
00162 virtual int processEvents()
00163 {
00164 pollTasks();
00165
00166 if (!theTasks.entries())
00167 stopPolling();
00168
00169 return theTasks.entries() > 0;
00170 }
00171
00172
00173 static void stopPolling()
00174 {
00175 #if defined(DEMO_DEBUG)
00176 fprintf(stderr, "Stop polling\n");
00177 #endif
00178 if (theTimer)
00179 {
00180
00181
00182 theTimer->uninstallGenerator();
00183 delete theTimer;
00184 theTimer = NULL;
00185 }
00186 }
00187
00188 static void startPolling()
00189 {
00190
00191 if (!theTimer)
00192 {
00193 #if defined(DEMO_DEBUG)
00194 fprintf(stderr, "Start polling\n");
00195 #endif
00196 theTimer = new BackgroundTimer();
00197
00198
00199 if (!theTimer->installGenerator())
00200 {
00201 delete theTimer;
00202 theTimer = NULL;
00203 }
00204 }
00205 }
00206 private:
00207 static BackgroundTimer *theTimer;
00208 };
00209
00210 BackgroundTimer *BackgroundTimer::theTimer = NULL;
00211
00212
00213 static void
00214 hdk_background(CMD_Args &args)
00215 {
00216 if (args.found('l'))
00217 listTasks(args.out());
00218 else if (args.argc() != 2)
00219 {
00220 args.err() << "Usage: " << args(0) << " [-l] 'command'\n";
00221 args.err() << "Runs a command in the background\n";
00222 args.err() << "The -l option lists all current commands\n";
00223 }
00224 else
00225 {
00226 BackgroundTask *task;
00227 task = new BackgroundTask();
00228 if (task->open(args(1)))
00229 {
00230 theTasks.append(task);
00231 BackgroundTimer::startPolling();
00232 }
00233 else
00234 {
00235 args.err() << "Error running: " << args(1) << endl;
00236 }
00237 }
00238 }
00239
00240 }
00241
00242
00243
00244 void
00245 CMDextendLibrary(CMD_Manager *cman)
00246 {
00247
00248 cman->installCommand("hdk_background", "l", HDK_Sample::hdk_background);
00249 }