Added "TCharm Semaphores", a bizarre way of moving pointers
authorOrion Lawlor <olawlor@acm.org>
Tue, 8 Apr 2003 21:34:23 +0000 (21:34 +0000)
committerOrion Lawlor <olawlor@acm.org>
Tue, 8 Apr 2003 21:34:23 +0000 (21:34 +0000)
between threads.  I'm not happy with the interface, so
this one's undocumented for now.

src/libs/ck-libs/tcharm/tcharm.C
src/libs/ck-libs/tcharm/tcharm_impl.h

index e061fb94e77445fb102055fa670fecff45e0c67f..c3fb65ef794a029c970bfe81010e22309ea3a869 100644 (file)
@@ -147,6 +147,9 @@ void TCharm::pup(PUP::er &p) {
   p(isStopped); p(resumeAfterMigration);
   p(threadInfo.thisElement);
   p(threadInfo.numElements);
+  
+  if (sema.size()>0) 
+       CkAbort("TCharm::pup> Cannot migrate with unconsumed semaphores!\n");
 
 #ifndef CMK_OPTIMIZE
   DBG("Packing thread");
@@ -178,7 +181,7 @@ void TCharm::pup(PUP::er &p) {
   p(nUd);
   for(int i=0;i<nUd;i++)
     ud[i].pup(p);
-  p|sud;
+  pupCkVec(p,sud);
   TCharm::setState(inFramework);
 
   if (!p.isUnpacking())
@@ -833,4 +836,54 @@ FDECL void FTN_NAME(TCHARM_INIT,tcharm_init)(void)
        _initCharm(argc,argv);
 }
 
+// TCHARM Semaphores
+/// Find this semaphore, or insert if there isn't one:
+TCharm::TCharmSemaphore *TCharm::findSema(int id) {
+       for (int s=0;s<sema.size();s++)
+               if (sema[s].id==id) 
+                       return &sema[s];
+       sema.push_back(TCharmSemaphore(id));
+       return &sema[sema.size()-1];
+}
+/// Remove this semaphore from the list
+void TCharm::freeSema(TCharmSemaphore *doomed) {
+       int id=doomed->id;
+       for (int s=0;s<sema.size();s++)
+               if (sema[s].id==id) {
+                       sema[s]=sema[sema.length()-1];
+                       sema.length()--;
+                       return;
+               }
+       CkAbort("Tried to free nonexistent TCharm semaphore");
+}
+
+/// Store data at the semaphore "id".
+///  The put can come before or after the get.
+void TCharm::semaPut(int id,void *data) {
+       TCharmSemaphore *s=findSema(id);
+       if (s->data!=NULL) CkAbort("Duplicate calls to TCharm::semaPut!");
+       s->data=data;
+       if (s->thread!=NULL) //Awaken the thread
+               resume();
+}
+
+/// Retreive data from the semaphore "id".
+///  Blocks if the data is not immediately available.
+///  Consumes the data, so another put will be required for the next get.
+void *TCharm::semaGet(int id) {
+       TCharmSemaphore *s=findSema(id);
+       if (s->data==NULL) 
+       { //Semaphore isn't filled yet: wait until it is
+               s->thread=CthSelf();
+               suspend(); //Will be woken by semaPut
+               // Semaphore may have moved-- find it again
+               s=findSema(id);
+               if (s->data==NULL) CkAbort("TCharm::semaGet awoken too early!");
+       }
+       void *ret=s->data;
+       // Now remove the semaphore from the list:
+       freeSema(s);
+       return ret;
+}
+
 #include "tcharm.def.h"
index 5613f6ddc3f62cf07cf704fed9dad17c6dfa16bc..9a143137e1f5483e66a8bff023089a77d4e28e78 100644 (file)
@@ -91,6 +91,29 @@ class TCharm: public CBase_TCharm
        };
        //New interface for user data:
        CkVec<UserData> sud;
+       
+       //Tiny semaphore-like pointer producer/consumer
+       class TCharmSemaphore {
+       public:
+               int id; //User-defined identifier
+               void *data; //User-defined data
+               CthThread thread; //Waiting thread, or 0 if none
+               
+               TCharmSemaphore() { id=-1; data=NULL; thread=NULL; }
+               TCharmSemaphore(int id_) { id=id_; data=NULL; thread=NULL; }
+       };
+       /// Short, unordered list of waiting semaphores.
+       CkVec<TCharmSemaphore> sema;
+       TCharmSemaphore *findSema(int id);
+       void freeSema(TCharmSemaphore *);
+       
+       /// Store data at the semaphore "id".
+       ///  The put can come before or after the get.
+       void semaPut(int id,void *data);
+       /// Retreive data from the semaphore "id".
+       ///  Blocks if the data is not immediately available.
+       ///  Consumes the data, so another put will be required for the next get.
+       void *semaGet(int id);
 
        //One-time initialization
        static void nodeInit(void);