e1133f0a8f384a4adc7b528e822507dfd296536c
[charm.git] / src / libs / ck-libs / pythonCCS / PythonCCS.C
1 #include "PythonCCS.h"
2
3 CsvDeclare(CmiNodeLock, pyLock);
4 CsvDeclare(PythonTable *, pyWorkers);
5 CsvDeclare(CmiUInt4, pyNumber);
6 CtvDeclare(PyObject *, pythonReturnValue);
7
8 // One-time per-processor setup routine
9 // main interface for python to access common charm methods
10 static PyObject *CkPy_printstr(PyObject *self, PyObject *args) {
11   char *stringToPrint;
12   if (!PyArg_ParseTuple(args, "s:printstr", &stringToPrint)) return NULL;
13   CkPrintf("%s\n",stringToPrint);
14   Py_INCREF(Py_None);return Py_None; //Return-nothing idiom
15 }
16
17 static inline void Ck_printclient(CmiUInt4 ref, char* str) {
18     CmiLock(CsvAccess(pyLock));
19   //PythonObject *pyWorker = ((*CsvAccess(pyWorkers))[pyReference]).object;
20   if (((*CsvAccess(pyWorkers))[ref]).clientReady > 0) {
21     // return the string to the client
22     // since there is a client waiting, it means there must not be
23     // pending strings to be returned ("printed" is empty)
24     //CkPrintf("printing data to the client\n");
25     CcsDelayedReply client = ((*CsvAccess(pyWorkers))[ref]).client;
26     CcsSendDelayedReply(client, strlen(str), str);
27     ((*CsvAccess(pyWorkers))[ref]).printed.erase();
28     ((*CsvAccess(pyWorkers))[ref]).clientReady = 0;
29   } else {
30     // add the string to those in list to be returned if it is keepPrint
31     if (((*CsvAccess(pyWorkers))[ref]).isKeepPrint) {
32       ((*CsvAccess(pyWorkers))[ref]).printed += std::string(str);
33     }
34     // else just drop the line
35   }
36   CmiUnlock(CsvAccess(pyLock));
37 }
38
39 static PyObject *CkPy_print(PyObject *self, PyObject *args) {
40   char *stringToPrint;
41   if (!PyArg_ParseTuple(args, "s:printclient", &stringToPrint)) return NULL;
42   CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(PyModule_GetDict(PyImport_AddModule("__main__")),"__charmNumber__"));
43   Ck_printclient(pyReference, stringToPrint);
44   Py_INCREF(Py_None);return Py_None; //Return-nothing idiom
45 }
46
47 static PyObject *CkPy_mype(PyObject *self, PyObject *args) {
48   if (!PyArg_ParseTuple(args, ":mype")) return NULL;
49   return Py_BuildValue("i", CkMyPe());
50 }
51
52 static PyObject *CkPy_numpes(PyObject *self, PyObject *args) {
53   if (!PyArg_ParseTuple(args, ":numpes")) return NULL;
54   return Py_BuildValue("i", CkNumPes());
55 }
56
57 static PyObject *CkPy_myindex(PyObject *self, PyObject *args) {
58   if (!PyArg_ParseTuple(args, ":myindex")) return NULL;
59   CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(PyModule_GetDict(PyImport_AddModule("__main__")),"__charmNumber__"));
60   CmiLock(CsvAccess(pyLock));
61   ArrayElement1D *pyArray1 = dynamic_cast<ArrayElement1D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
62   ArrayElement2D *pyArray2 = dynamic_cast<ArrayElement2D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
63   ArrayElement3D *pyArray3 = dynamic_cast<ArrayElement3D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
64   ArrayElement4D *pyArray4 = dynamic_cast<ArrayElement4D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
65   ArrayElement5D *pyArray5 = dynamic_cast<ArrayElement5D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
66   ArrayElement6D *pyArray6 = dynamic_cast<ArrayElement6D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
67   CmiUnlock(CsvAccess(pyLock));
68   if (pyArray1) return Py_BuildValue("(i)", pyArray1->thisIndex);
69   else if (pyArray2) return Py_BuildValue("(ii)", pyArray2->thisIndex.x, pyArray2->thisIndex.y);
70   else if (pyArray3) return Py_BuildValue("(iii)", pyArray3->thisIndex.x, pyArray3->thisIndex.y, pyArray3->thisIndex.z);
71   else if (pyArray4) return Py_BuildValue("(iiii)", pyArray4->thisIndex.w, pyArray4->thisIndex.x, pyArray4->thisIndex.y, pyArray4->thisIndex.z);
72   else if (pyArray5) return Py_BuildValue("(iiiii)", pyArray5->thisIndex.v, pyArray5->thisIndex.w, pyArray5->thisIndex.x, pyArray5->thisIndex.y, pyArray5->thisIndex.z);
73   else if (pyArray6) return Py_BuildValue("(iiiiii)", pyArray6->thisIndex.x1, pyArray6->thisIndex.y1, pyArray6->thisIndex.z1, pyArray6->thisIndex.x2, pyArray6->thisIndex.y2, pyArray6->thisIndex.z2);
74   else { Py_INCREF(Py_None);return Py_None;}
75   //return Py_BuildValue("i", (*CsvAccess(pyWorkers))[0]->thisIndex);
76 }
77
78 // method to read a variable and convert it to a python object
79 static PyObject *CkPy_read(PyObject *self, PyObject *args) {
80   if (!PyArg_ParseTuple(args, "O:read")) return NULL;
81   CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(PyModule_GetDict(PyImport_AddModule("__main__")),"__charmNumber__"));
82   CmiLock(CsvAccess(pyLock));
83   PythonObject *pyWorker = ((*CsvAccess(pyWorkers))[pyReference]).object;
84   CmiUnlock(CsvAccess(pyLock));
85   return pyWorker->read(args);
86 }
87
88 // method to convert a python object into a variable and write it
89 static PyObject *CkPy_write(PyObject *self, PyObject *args) {
90   PyObject *where, *what;
91   if (!PyArg_ParseTuple(args, "OO:write",&where,&what)) return NULL;
92
93   /* Problem solving:
94
95      when the calling parameters (where and what) are formed by only one value,
96      the parsing done here above will return two objects which are not tuples
97      (and no parenthesis on the caller will change this). For this reason, we
98      have to recreate two new tuples with the given argements to pass to the
99      write function of the object.
100   */
101   PyObject *whereT, *whatT;
102   if (PyTuple_Check(where)) whereT = where;
103   else {
104     whereT = PyTuple_New(1);
105     PyTuple_SET_ITEM(whereT, 0, where);
106   }
107   if (PyTuple_Check(what)) whatT = what;
108   else {
109     whatT = PyTuple_New(1);
110     PyTuple_SET_ITEM(whatT, 0, what);
111   }
112   CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(PyModule_GetDict(PyImport_AddModule("__main__")),"__charmNumber__"));
113   CmiLock(CsvAccess(pyLock));
114   PythonObject *pyWorker = ((*CsvAccess(pyWorkers))[pyReference]).object;
115   CmiUnlock(CsvAccess(pyLock));
116   pyWorker->write(whereT, whatT);
117   Py_DECREF(whereT);
118   Py_DECREF(whatT);
119   Py_INCREF(Py_None);return Py_None;
120 }
121
122 PyMethodDef PythonObject::CkPy_MethodsCustom[] = {
123   {NULL,      NULL}        /* Sentinel */
124 };
125
126 char* PythonObject::CkPy_MethodsCustomDoc = "";
127
128 PyMethodDef CkPy_MethodsDefault[] = {
129   {"printstr", CkPy_printstr, METH_VARARGS},
130   {"printclient", CkPy_print, METH_VARARGS},
131   {"mype", CkPy_mype, METH_VARARGS},
132   {"numpes", CkPy_numpes, METH_VARARGS},
133   {"myindex", CkPy_myindex, METH_VARARGS},
134   {"read", CkPy_read, METH_VARARGS},
135   {"write", CkPy_write, METH_VARARGS},
136   {NULL,      NULL}        /* Sentinel */
137 };
138
139 void PythonObject::pyRequest (CkCcsRequestMsg *msg) {
140   PythonAbstract *pyAbstract = (PythonAbstract *)msg->data;
141   pyAbstract->unpack();
142
143   if (pyAbstract->isExecute()) {
144     execute(msg, &msg->reply);
145     // the message is not deleted here, it will deleted by the function itself
146     // deleting it here creates problems with the high level scripting where
147     // a new thread is created. the alternative will be to memcopy the message
148   } else if (pyAbstract->isPrint()) {
149     print((PythonPrint *)msg->data, &msg->reply);
150     delete msg;
151   } else if (pyAbstract->isFinished()) {
152     finished((PythonFinished *)msg->data, &msg->reply);
153     delete msg;
154   } else {
155     CkPrintf("Wrong request arrived!\n");
156     delete msg;
157   }
158 }
159
160
161 void PythonObject::print (PythonPrint *pyMsg, CcsDelayedReply *reply) {
162   // ATTN: be sure that in all possible paths pyLock is released!
163   CmiLock(CsvAccess(pyLock));
164   CmiUInt4 returnValue;
165   pyMsg->unpack();
166
167   PythonTable::iterator iter = CsvAccess(pyWorkers)->find(pyMsg->interpreter);
168   if (iter == CsvAccess(pyWorkers)->end()) {
169     // Malformed request!
170     //CkPrintf("PythonCCS: print request on invalid interpreter\n");
171     CmiUnlock(CsvAccess(pyLock));
172     returnValue = htonl(0);
173     CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
174   } else {
175     // it is a correct print request, parse it
176
177     if (pyMsg->isKill()) {
178       // kill the pending client print request
179       if (iter->second.clientReady == 1) {
180         returnValue = htonl(0);
181         CcsSendDelayedReply(iter->second.client, sizeof(CmiUInt4), (void *)&returnValue);
182       }
183       CmiUnlock(CsvAccess(pyLock));
184       // do no return anything to the calling socket
185       CcsNoDelayedReply(*reply);
186       return;
187     }
188
189     // is something already printed?
190     if (iter->second.printed.length() > 0) {
191       // send back to the client the string
192       const char *str = iter->second.printed.c_str();
193       //CkPrintf("sending data to the client\n");
194       CcsSendDelayedReply(*reply, strlen(str), str);
195       iter->second.printed.erase();
196       if (iter->second.clientReady == -1) {
197         // after the client flush the printed buffer, delete the entry
198         CsvAccess(pyWorkers)->erase(pyMsg->interpreter);
199       }
200     } else {
201       // nothing printed, store the client request if it will be waiting
202       if (pyMsg->isWait()) {
203         // check if someone else has requested prints, if yes, kill the other
204         if (iter->second.clientReady == 1) {
205           returnValue = htonl(0);
206           CcsSendDelayedReply(iter->second.client, sizeof(CmiUInt4), (void *)&returnValue);
207         }
208         iter->second.client = *reply;
209         iter->second.clientReady = 1;
210       } else {
211         // return null
212         returnValue = htonl(0);
213         CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
214       }
215     }
216     CmiUnlock(CsvAccess(pyLock));
217   }
218 }
219
220 void PythonObject::finished (PythonFinished *pyMsg, CcsDelayedReply *reply) {
221    // ATTN: be sure that in all possible paths pyLock is released!
222   CmiLock(CsvAccess(pyLock));
223   CmiUInt4 pyReference = pyMsg->interpreter;
224   CmiUInt4 returnValue;
225   pyMsg->unpack();
226
227   PythonTable::iterator iter = CsvAccess(pyWorkers)->find(pyMsg->interpreter);
228   if (iter == CsvAccess(pyWorkers)->end() || !iter->second.inUse) {
229     //ckout <<"answering Finished yes"<<endl;
230     returnValue = htonl(pyReference);
231     CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
232     CmiUnlock(CsvAccess(pyLock));
233     return;
234   }
235
236   // the client is in use
237   if (pyMsg->isWait()) {
238     // is there another client waiting for termination?
239     if (iter->second.finishReady) {
240       // kill the previous requester
241       returnValue = htonl(0);
242       CcsSendDelayedReply(iter->second.finish, sizeof(CmiUInt4), (void *)&returnValue);
243     }
244     //ckout <<"queueing Finished request"<<endl;
245     iter->second.finish = *reply;
246     iter->second.finishReady = 1;
247   } else {
248     //ckout <<"answering Finished no"<<endl;
249     returnValue = htonl(0);
250     CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
251   }
252   CmiUnlock(CsvAccess(pyLock));
253 }
254
255 void PythonObject::execute (CkCcsRequestMsg *msg, CcsDelayedReply *reply) {
256   // ATTN: be sure that in all possible paths pyLock is released!
257   PythonExecute *pyMsg = (PythonExecute *)msg->data;
258   PyEval_AcquireLock();
259   CmiLock(CsvAccess(pyLock));
260   CmiUInt4 pyReference;
261   CmiUInt4 returnValue;
262
263   // re-establish the pointers in the structure
264   pyMsg->unpack();
265
266   if (pyMsg->interpreter > 0) {
267     // the user specified an interpreter, check if it is free
268     PythonTable::iterator iter;
269     if ((iter=CsvAccess(pyWorkers)->find(pyMsg->interpreter))!=CsvAccess(pyWorkers)->end() && !iter->second.inUse && iter->second.clientReady!=-1) {
270       // the interpreter already exists and it is neither in use, nor dead
271       //CkPrintf("interpreter present and not in use\n");
272       pyReference = pyMsg->interpreter;
273       PyThreadState_Swap(iter->second.pythread);
274       //PyEval_AcquireLock();
275     } else {
276       // ops, either the iterator does not exist or is already in use, return an
277       // error to the client, we don't want to create a new interpreter if the
278       // old is in use, because this can corrupt the semantics of the user code.
279       //if (iter==CsvAccess(pyWorkers)->end()) CkPrintf("asked for an interpreter not present\n");
280       //else CkPrintf("interpreter already in use\n");
281       returnValue = htonl(0);
282       CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
283       CmiUnlock(CsvAccess(pyLock));
284       PyEval_ReleaseLock();
285       return;  // stop the execution
286     }
287   } else {
288     // the user didn't specify an interpreter, create a new one
289     //CkPrintf("creating new interpreter\n");
290
291     // update the reference number, used to access the current chare
292     pyReference = ++CsvAccess(pyNumber);
293     CsvAccess(pyNumber) &= ~(1<<31);
294     ((*CsvAccess(pyWorkers))[pyReference]).object = this;
295     ((*CsvAccess(pyWorkers))[pyReference]).clientReady = 0;
296
297     // create the new interpreter
298     //PyEval_AcquireLock();
299     PyThreadState *pts = Py_NewInterpreter();
300
301     CkAssert(pts != NULL);
302     ((*CsvAccess(pyWorkers))[pyReference]).pythread = pts;
303
304     Py_InitModule("ck", CkPy_MethodsDefault);
305     if (pyMsg->isHighLevel()) Py_InitModule("charm", getMethods());
306
307     // insert into the dictionary a variable with the reference number
308     PyObject *mod = PyImport_AddModule("__main__");
309     PyObject *dict = PyModule_GetDict(mod);
310
311     PyDict_SetItemString(dict,"__charmNumber__",PyInt_FromLong(pyReference));
312     PyRun_String("import ck\nimport sys\n"
313                  "ck.__doc__ = \"Ck module: basic charm routines\\n"
314                  "printstr(str) -- print a string on the server\\n"
315                  "printclient(str) -- print a string on the client\\n"
316                  "mype() -- return an integer for MyPe()\\n"
317                  "numpes() -- return an integer for NumPes()\\n"
318                  "myindex() -- return a tuple containing the array index (valid only for arrays)\\n"
319                  "read(where) -- read a value on the chare (uses the \\\"read\\\" method of the chare)\\n"
320                  "write(where, what) -- write a value back on the chare (uses the \\\"write\\\" method of the chare)\\n\"",
321                  Py_file_input,dict,dict);
322     if (pyMsg->isHighLevel()) {
323       PyRun_String("import charm",Py_file_input,dict,dict);
324       PyRun_String(getMethodsDoc(),Py_file_input,dict,dict);
325     }
326
327     PyRun_String("class __charmOutput__:\n"
328                  "    def __init__(self, stdout):\n"
329                  "        self.stdout = stdout\n"
330                  "    def write(self, s):\n"
331                  "        ck.printclient(s)\n"
332                  "sys.stdout = __charmOutput__(sys.stdout)"
333                  ,Py_file_input,dict,dict);
334
335   }
336
337   ((*CsvAccess(pyWorkers))[pyReference]).inUse = true;
338   if (pyMsg->isKeepPrint()) {
339     ((*CsvAccess(pyWorkers))[pyReference]).isKeepPrint = true;
340   } else {
341     ((*CsvAccess(pyWorkers))[pyReference]).isKeepPrint = false;
342   }
343
344   if (pyMsg->isWait()) {
345     ((*CsvAccess(pyWorkers))[pyReference]).finish = *reply;
346     ((*CsvAccess(pyWorkers))[pyReference]).finishReady = 1;
347   } else {
348     ((*CsvAccess(pyWorkers))[pyReference]).finishReady = 0;
349     // send back this number to the client, which is an ack
350     ckout<<"new interpreter created "<<pyReference<<endl;
351     returnValue = htonl(pyReference);
352     CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
353   }
354
355   //if (((*CsvAccess(pyWorkers))[pyReference]).object != this) ckout<<"object not this"<<endl;
356   //else ckout<<"object ok"<<endl;
357
358   CmiUnlock(CsvAccess(pyLock));
359
360   // run the program
361   if (pyMsg->isHighLevel()) {
362     CthResume(CthCreate((CthVoidFn)_callthr_executeThread, new CkThrCallArg(msg,this), 0));
363     // msg is delete inside the newly created thread
364   } else {
365     executeThread(pyMsg);
366     // delete the message, execute was delegated
367     delete msg;
368   }
369 }
370
371 // created in a new thread, call the executeThread method
372 // we know that the impl_msg contains a CkCcsRequestMsg which data is a
373 // PythonExecute, so we pass directly this latest parameter
374 void PythonObject::_callthr_executeThread(CkThrCallArg *impl_arg) {
375   CkCcsRequestMsg *impl_msg = (CkCcsRequestMsg*)impl_arg->msg;
376   PythonObject *impl_obj = (PythonObject *) impl_arg->obj;
377   delete impl_arg;
378
379   impl_obj->executeThread((PythonExecute*)impl_msg->data);
380   delete impl_msg;
381 }
382
383 void PythonObject::executeThread(PythonExecute *pyMsg) {
384   // get the information about the running python thread and my reference number
385   //ckout << "options  "<<pyMsg->isPersistent()<<endl;
386   PyThreadState *mine = PyThreadState_Get();
387   PyObject *dict = PyModule_GetDict(PyImport_AddModule("__main__"));
388   CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(dict,"__charmNumber__"));
389
390   // store the self thread for future suspention if high level execution
391   if (pyMsg->isHighLevel()) {
392     CmiLock(CsvAccess(pyLock));
393     ((*CsvAccess(pyWorkers))[pyReference]).thread=CthSelf();
394     CmiUnlock(CsvAccess(pyLock));
395   }
396
397   // decide whether it is iterative or not
398   if (!pyMsg->isIterate()) {
399     PyObject* python_output = PyRun_String(pyMsg->code.code, Py_file_input, dict, dict);
400     //PyRun_SimpleString(pyMsg->code.code);
401     //CkPrintf("python_output = %d\n",python_output);
402     if (python_output == NULL) {
403       // return the string error to the client
404       PyObject *ptype, *pvalue, *ptraceback;
405       PyErr_Fetch(&ptype, &pvalue, &ptraceback);
406       PyObject *strP = PyObject_Str(ptype);
407       char *str = PyString_AsString(strP);
408       Ck_printclient(pyReference, str);
409       //CkPrintf("%s\n",str);
410       Py_DECREF(strP);
411       Ck_printclient(pyReference, ": ");
412       strP = PyObject_Str(pvalue);
413       str = PyString_AsString(strP);
414       Ck_printclient(pyReference, str);
415       //CkPrintf("%s\n",str);
416       Py_DECREF(strP);
417       //PyObject_Print(ptype, stdout, 0);
418       //CkPrintf("   %d %d %d %d\n",PyType_Check(ptype),PyString_Check(ptype),PyList_Check(ptype),PyTuple_Check(ptype));
419       //PyObject_Print(pvalue, stdout, 0);
420       //CkPrintf("   %d %d %d %d\n",PyType_Check(pvalue),PyString_Check(pvalue),PyList_Check(pvalue),PyTuple_Check(pvalue));
421       //PyObject_Print(ptraceback, stdout, 0);
422       //if (ptraceback) CkPrintf("   %d %d %d %d\n",PyType_Check(ptraceback),PyString_Check(ptraceback),PyList_Check(ptraceback),PyTuple_Check(ptraceback));
423     }
424   } else {
425     // compile the program
426     char *userCode = pyMsg->code.code;
427     struct _node* programNode = PyParser_SimpleParseString(userCode, Py_file_input);
428     if (programNode==NULL) {
429       CkPrintf("Program Parse Error\n");
430       // distroy map element in pyWorkers and terminate interpreter
431       cleanup(pyMsg, mine, pyReference);
432       return;
433     }
434     PyCodeObject *program = PyNode_Compile(programNode, "");
435     if (program==NULL) {
436       CkPrintf("Program Compile Error\n");
437       PyNode_Free(programNode);
438       // distroy map element in pyWorkers and terminate interpreter
439       cleanup(pyMsg, mine, pyReference);
440       return;
441     }
442     PyObject *mod = PyImport_AddModule("__main__");
443     PyObject *dict = PyModule_GetDict(mod);
444     PyObject *code = PyEval_EvalCode(program, dict, dict);
445     if (code==NULL) {
446       CkPrintf("Program Eval Error\n");
447       PyNode_Free(programNode);
448       Py_DECREF(program);
449       // distroy map element in pyWorkers and terminate interpreter
450       cleanup(pyMsg, mine, pyReference);
451       return;
452     }
453
454     // load the user defined method
455     char *userMethod = pyMsg->methodName.methodName;
456     PyObject *item = PyDict_GetItemString(dict, userMethod);
457     if (item==NULL) {
458       CkPrintf("Method not found\n");
459       PyNode_Free(programNode);
460       Py_DECREF(program);
461       Py_DECREF(code);
462       // distroy map element in pyWorkers and terminate interpreter
463       cleanup(pyMsg, mine, pyReference);
464       return;
465     }
466
467     // create the container for the data
468     PyRun_String("class Particle:\n\tpass\n\n", Py_file_input, dict, dict);
469     PyObject *part = PyRun_String("Particle()", Py_eval_input, dict, dict);
470     PyObject *arg = PyTuple_New(1);
471     PyTuple_SetItem(arg, 0, part);
472
473     // construct the iterator calling the user defined method in the interiting class
474     PythonIterator *userIterator = pyMsg->info.info;
475     int more = buildIterator(part, userIterator);
476
477     // iterate over all the provided iterators from the user class
478     PyObject *result;
479     while (more) {
480       result = PyObject_CallObject(item, arg);
481       if (!result) {
482         CkPrintf("Python Call error\n");
483         PyErr_Print();
484         break;
485       }
486       more = nextIteratorUpdate(part, result, userIterator);
487       Py_DECREF(result);
488     }
489
490     Py_DECREF(part);
491     Py_DECREF(arg);
492     PyNode_Free(programNode);
493     Py_DECREF(program);
494     Py_DECREF(code);
495
496   } // end decision if it is iterate or not
497
498   cleanup(pyMsg, mine, pyReference);
499
500 }
501
502 // this function takes care of destroying the interpreter, deleting the
503 // reference into the map table, depending on the flags specified
504 void PythonObject::cleanup (PythonExecute *pyMsg, PyThreadState *pts, CmiUInt4 pyReference) {
505   CmiUInt4 returnValue;
506
507   //ckout <<"cleanup called"<<endl;
508   CmiLock(CsvAccess(pyLock));
509   // if there is someone waiting for finish, send ackowledge
510   if (((*CsvAccess(pyWorkers))[pyReference]).finishReady) {
511     //ckout <<"answering the client finish"<<endl;
512     returnValue = htonl(pyReference);
513     CcsSendDelayedReply(((*CsvAccess(pyWorkers))[pyReference]).finish, sizeof(CmiUInt4), (void *)&returnValue);
514     ((*CsvAccess(pyWorkers))[pyReference]).finishReady = 0;
515   }
516
517   //ckout << "options"<<pyMsg->isPersistent()<<endl;
518   ((*CsvAccess(pyWorkers))[pyReference]).inUse = false;
519   if (!pyMsg->isPersistent()) {
520     Py_EndInterpreter(pts);
521     ((*CsvAccess(pyWorkers))[pyReference]).clientReady = -1;
522   }
523   PyEval_ReleaseLock();
524
525   if (!pyMsg->isPersistent() && ((*CsvAccess(pyWorkers))[pyReference]).printed.length()==0) {
526     // destroy the entry in the map
527     //CkPrintf("destroyed interpreter\n");
528     CsvAccess(pyWorkers)->erase(pyReference);
529   }
530   CmiUnlock(CsvAccess(pyLock));
531 }
532
533 /*
534 void PythonObject::iterate (CkCcsRequestMsg *msg) {
535
536   // update the reference number, used to access the current chare
537   CmiLock(CsvAccess(pyLock));
538   CmiUInt4 pyReference = CsvAccess(pyNumber)++;
539   CsvAccess(pyNumber) &= ~(1<<31);
540   ((*CsvAccess(pyWorkers))[pyReference]).object = this;
541   CmiUnlock(CsvAccess(pyLock));
542
543   // send back this number to the client
544   CcsSendDelayedReply(msg->reply, 1, (void *)&pyReference);
545
546   // create the new interpreter
547   PyEval_AcquireLock();
548   PyThreadState *pts = Py_NewInterpreter();
549   Py_InitModule("ck", CkPy_MethodsDefault);
550
551   // insert into the dictionary a variable with the reference number
552   PyObject *mod = PyImport_AddModule("__main__");
553   PyObject *dict = PyModule_GetDict(mod);
554
555   PyDict_SetItemString(dict,"__charmNumber__",PyInt_FromLong(pyReference));
556
557   // compile the program
558   char *userCode = (char *)msg->data;
559   struct _node* programNode = PyParser_SimpleParseString(userCode, Py_file_input);
560   if (programNode==NULL) {
561     CkPrintf("Program error\n");
562     // distroy map element in pyWorkers and terminate interpreter
563     Py_EndInterpreter(pts);
564     PyEval_ReleaseLock();
565     CmiLock(CsvAccess(pyLock));
566     CsvAccess(pyWorkers)->erase(pyReference);
567     CmiUnlock(CsvAccess(pyLock));
568     delete msg;
569     return;
570   }
571   PyCodeObject *program = PyNode_Compile(programNode, "");
572   if (program==NULL) {
573     CkPrintf("Program error\n");
574     PyNode_Free(programNode);
575     // distroy map element in pyWorkers and terminate interpreter
576     Py_EndInterpreter(pts);
577     PyEval_ReleaseLock();
578     CmiLock(CsvAccess(pyLock));
579     CsvAccess(pyWorkers)->erase(pyReference);
580     CmiUnlock(CsvAccess(pyLock));
581     delete msg;
582     return;
583   }
584   PyObject *code = PyEval_EvalCode(program, dict, dict);
585   if (code==NULL) {
586     CkPrintf("Program error\n");
587     PyNode_Free(programNode);
588     Py_DECREF(program);
589     // distroy map element in pyWorkers and terminate interpreter
590     Py_EndInterpreter(pts);
591     PyEval_ReleaseLock();
592     CmiLock(CsvAccess(pyLock));
593     CsvAccess(pyWorkers)->erase(pyReference);
594     CmiUnlock(CsvAccess(pyLock));
595     delete msg;
596     return;
597   }
598
599   // load the user defined method
600   char *userMethod = userCode + strlen(userCode) + 1;
601   PyObject *item = PyDict_GetItemString(dict, userMethod);
602   if (item==NULL) {
603     CkPrintf("Method not found\n");
604     PyNode_Free(programNode);
605     Py_DECREF(program);
606     Py_DECREF(code);
607     // distroy map element in pyWorkers and terminate interpreter
608     Py_EndInterpreter(pts);
609     PyEval_ReleaseLock();
610     CmiLock(CsvAccess(pyLock));
611     CsvAccess(pyWorkers)->erase(pyReference);
612     CmiUnlock(CsvAccess(pyLock));
613     delete msg;
614     return;
615   }
616
617   // create the container for the data
618   PyRun_String("class Particle:\n\tpass\n\n", Py_file_input, dict, dict);
619   PyObject *part = PyRun_String("Particle()", Py_eval_input, dict, dict);
620   PyObject *arg = PyTuple_New(1);
621   PyTuple_SetItem(arg, 0, part);
622
623   // construct the iterator calling the user defined method in the interiting class
624   void *userIterator = (void *)(userMethod + strlen(userMethod) + 1);
625   int more = buildIterator(part, userIterator);
626
627   // iterate over all the provided iterators from the user class
628   PyObject *result;
629   while (more) {
630     result = PyObject_CallObject(item, arg);
631     if (!result) {
632       CkPrintf("Python Call error\n");
633       break;
634     }
635     more = nextIteratorUpdate(part, result, userIterator);
636     Py_DECREF(result);
637   }
638
639   Py_DECREF(part);
640   Py_DECREF(arg);
641   PyNode_Free(programNode);
642   Py_DECREF(program);
643   Py_DECREF(code);
644
645   // distroy map element in pyWorkers and terminate interpreter
646   Py_EndInterpreter(pts);
647   PyEval_ReleaseLock();
648   CmiLock(CsvAccess(pyLock));
649   CsvAccess(pyWorkers)->erase(pyReference);
650   CmiUnlock(CsvAccess(pyLock));
651   delete msg;
652 }
653 */
654
655 void PythonObject::getPrint(CkCcsRequestMsg *msg) {
656
657 }
658
659 static void initializePythonDefault(void) {
660   CsvInitialize(CmiUInt, pyNumber);
661   CsvAccess(pyNumber) = 0;
662   CsvInitialize(PythonTable *,pyWorkers);
663   CsvAccess(pyWorkers) = new PythonTable();
664   CsvInitialize(CmiNodeLock, pyLock);
665   CsvAccess(pyLock) = CmiCreateLock();
666   CtvInitialize(PyObject *,pythonReturnValue);
667
668   Py_Initialize();
669   PyEval_InitThreads();
670
671   PyEval_ReleaseLock();
672 }
673
674 // a bunch of routines to ease the user code
675 void PythonObject::pythonSetString(PyObject *arg, char *descr, char *value) {
676   PyObject *tmp = PyString_FromString(value);
677   PyObject_SetAttrString(arg, descr, tmp);
678   Py_DECREF(tmp);
679 }
680
681 void PythonObject::pythonSetString(PyObject *arg, char *descr, char *value, int len) {
682   PyObject *tmp = PyString_FromStringAndSize(value, len);
683   PyObject_SetAttrString(arg, descr, tmp);
684   Py_DECREF(tmp);
685 }
686
687 void PythonObject::pythonGetString(PyObject *arg, char *descr, char **result) {
688   PyObject *tmp = PyObject_GetAttrString(arg, descr);
689   *result = PyString_AsString(tmp);
690   Py_DECREF(tmp);
691 }
692
693 void PythonObject::pythonSetInt(PyObject *arg, char *descr, long value) {
694   PyObject *tmp = PyInt_FromLong(value);
695   PyObject_SetAttrString(arg, descr, tmp);
696   Py_DECREF(tmp);
697 }
698
699 void PythonObject::pythonGetInt(PyObject *arg, char *descr, long *result) {
700   PyObject *tmp = PyObject_GetAttrString(arg, descr);
701   *result = PyInt_AsLong(tmp);
702   Py_DECREF(tmp);
703 }
704
705 void PythonObject::pythonSetLong(PyObject *arg, char *descr, long value) {
706   PyObject *tmp = PyLong_FromLong(value);
707   PyObject_SetAttrString(arg, descr, tmp);
708   Py_DECREF(tmp);
709 }
710
711 void PythonObject::pythonSetLong(PyObject *arg, char *descr, unsigned long value) {
712   PyObject *tmp = PyLong_FromUnsignedLong(value);
713   PyObject_SetAttrString(arg, descr, tmp);
714   Py_DECREF(tmp);
715 }
716
717 void PythonObject::pythonSetLong(PyObject *arg, char *descr, double value) {
718   PyObject *tmp = PyLong_FromDouble(value);
719   PyObject_SetAttrString(arg, descr, tmp);
720   Py_DECREF(tmp);
721 }
722
723 void PythonObject::pythonGetLong(PyObject *arg, char *descr, long *result) {
724   PyObject *tmp = PyObject_GetAttrString(arg, descr);
725   *result = PyLong_AsLong(tmp);
726   Py_DECREF(tmp);
727 }
728
729 void PythonObject::pythonGetLong(PyObject *arg, char *descr, unsigned long *result) {
730   PyObject *tmp = PyObject_GetAttrString(arg, descr);
731   *result = PyLong_AsUnsignedLong(tmp);
732   Py_DECREF(tmp);
733 }
734
735 void PythonObject::pythonGetLong(PyObject *arg, char *descr, double *result) {
736   PyObject *tmp = PyObject_GetAttrString(arg, descr);
737   *result = PyLong_AsDouble(tmp);
738   Py_DECREF(tmp);
739 }
740
741 void PythonObject::pythonSetFloat(PyObject *arg, char *descr, double value) {
742   PyObject *tmp = PyFloat_FromDouble(value);
743   PyObject_SetAttrString(arg, descr, tmp);
744   Py_DECREF(tmp);
745 }
746
747 void PythonObject::pythonGetFloat(PyObject *arg, char *descr, double *result) {
748   PyObject *tmp = PyObject_GetAttrString(arg, descr);
749   *result = PyFloat_AsDouble(tmp);
750   Py_DECREF(tmp);
751 }
752
753 void PythonObject::pythonSetComplex(PyObject *arg, char *descr, double real, double imag) {
754   PyObject *tmp = PyComplex_FromDoubles(real, imag);
755   PyObject_SetAttrString(arg, descr, tmp);
756   Py_DECREF(tmp);
757 }
758
759 void PythonObject::pythonGetComplex(PyObject *arg, char *descr, double *real, double *imag) {
760   PyObject *tmp = PyObject_GetAttrString(arg, descr);
761   *real = PyComplex_RealAsDouble(tmp);
762   *imag = PyComplex_ImagAsDouble(tmp);
763   Py_DECREF(tmp);
764 }
765
766 PyObject *PythonObject::pythonGetArg(int handle) {
767   CmiLock(CsvAccess(pyLock));
768   PyObject *result = ((*CsvAccess(pyWorkers))[handle]).arg;
769   CmiUnlock(CsvAccess(pyLock));
770   return result;
771 }
772
773 void PythonObject::pythonReturn(int handle) {
774   CmiLock(CsvAccess(pyLock));
775   CthThread handleThread = ((*CsvAccess(pyWorkers))[handle]).thread;
776   *((*CsvAccess(pyWorkers))[handle]).result = 0;
777   CmiUnlock(CsvAccess(pyLock));
778   CthAwaken(handleThread);
779 }
780
781 void PythonObject::pythonReturn(int handle, PyObject* data) {
782   CmiLock(CsvAccess(pyLock));
783   CthThread handleThread = ((*CsvAccess(pyWorkers))[handle]).thread;
784   *((*CsvAccess(pyWorkers))[handle]).result = data;
785   CmiUnlock(CsvAccess(pyLock));
786   CthAwaken(handleThread);
787 }
788
789 void PythonObject::pythonAwake(int handle) {
790   CmiLock(CsvAccess(pyLock));
791   PyThreadState *handleThread = ((*CsvAccess(pyWorkers))[handle]).pythread;
792   CmiUnlock(CsvAccess(pyLock));
793   PyEval_AcquireLock();
794   PyThreadState_Swap(handleThread);
795 }
796
797 void PythonObject::pythonSleep(int handle) {
798   PyEval_ReleaseLock();
799 }
800
801 #include "PythonCCS.def.h"