3349c1d2521e30d9fb440bc5100521233eddc1be
[charm.git] / src / ck-core / ckfutures.C
1 #include "charm++.h"
2 #include "ck.h"
3 #include "ckfutures.h"
4 #include <stdlib.h>
5
6 /******************************************************************************
7  *
8  * The sequential future abstraction.
9  *
10  *****************************************************************************/
11
12 typedef struct Future_s {
13   int ready;
14   void *value;
15   CthThread waiters;
16   int next; 
17 } Future;
18
19 typedef struct {
20   Future *array;
21   int max;
22   int freelist;
23 }
24 FutureState;
25
26 CpvStaticDeclare(FutureState, futurestate);
27
28 static void addedFutures(int lo, int hi)
29 {
30   int i;
31   FutureState *fs = &(CpvAccess(futurestate));
32   Future *array = fs->array;
33
34   for (i=lo; i<hi; i++)
35     array[i].next = i+1;
36   array[hi-1].next = fs->freelist;
37   fs->freelist = lo;
38 }
39
40 static int createFuture()
41 {
42   FutureState *fs = &(CpvAccess(futurestate));
43   Future *fut; int handle, origsize, newsize, i;
44
45   /* if the freelist is empty, allocate more futures. */
46   if (fs->freelist == -1) {
47     fs->max = fs->max * 2;
48     fs->array = (Future*)realloc(fs->array, sizeof(Future)*(fs->max));
49     addedFutures(origsize, newsize);
50   }
51   handle = fs->freelist;
52   fut = fs->array + handle;
53   fs->freelist = fut->next;
54   fut->ready = 0;
55   fut->value = 0;
56   fut->waiters = 0;
57   fut->next = 0;
58   return handle;
59 }
60
61 static void destroyFuture(int handle)
62 {
63   FutureState *fs = &(CpvAccess(futurestate));
64   Future *fut = (fs->array)+handle;
65   fut->next = fs->freelist;
66   fs->freelist = handle;
67 }
68
69 static void *waitFuture(int handle, int destroy)
70 {
71   CthThread self = CthSelf();
72   FutureState *fs = &(CpvAccess(futurestate));
73   Future *fut = (fs->array)+handle;
74   void *value;
75
76   if (!(fut->ready)) {
77     CthSetNext(self, fut->waiters);
78     fut->waiters = self;
79     CthSuspend();
80   }
81   value = fut->value;
82   if (destroy) destroyFuture(handle);
83   return value;
84 }
85
86 static void setFuture(int handle, void *pointer)
87 {
88   CthThread t;
89   FutureState *fs = &(CpvAccess(futurestate));
90   Future *fut = (fs->array)+handle;
91   fut->ready = 1;
92   fut->value = pointer;
93   for (t=fut->waiters; t; t=CthGetNext(t))
94     CthAwaken(t);
95   fut->waiters = 0;
96 }
97
98 void _futuresModuleInit(void)
99 {
100   int i; Future *array;
101   CpvInitialize(FutureState, futurestate);
102   CpvAccess(futurestate).array = (Future *)malloc(10*sizeof(Future));
103   CpvAccess(futurestate).max   = 10;
104   CpvAccess(futurestate).freelist = -1;
105   addedFutures(0,10);
106 }
107
108
109 /******************************************************************************
110  *
111  *
112  *****************************************************************************/
113
114 CProxy_FutureBOC fBOC(0);
115
116 class FutureInitMsg : public CMessage_FutureInitMsg {
117   public: int x ;
118 };
119
120 class  FutureMain : public Chare {
121   public:
122     FutureMain(CkArgMsg *m) {
123       fBOC.ckSetGroupId(CProxy_FutureBOC::ckNew(new FutureInitMsg));
124       CkFreeMsg(m);
125     }
126 };
127
128 extern "C" 
129 void *CkRemoteBranchCall(int ep, void *m, int group, int PE)
130
131   void * result;
132   envelope *env = UsrToEnv(m);
133   int i = createFuture();
134   env->setRef(i);
135   CkSendMsgBranch(ep, m, PE, group);
136   result = waitFuture(i, 1);
137   return (result);
138 }
139
140 extern "C" 
141 void *CkRemoteNodeBranchCall(int ep, void *m, int group, int node)
142
143   void * result;
144   envelope *env = UsrToEnv(m);
145   int i = createFuture();
146   env->setRef(i);
147   CkSendMsgNodeBranch(ep, m, node, group);
148   result = waitFuture(i, 1);
149   return (result);
150 }
151
152 extern "C" 
153 void *CkRemoteCall(int ep, void *m, CkChareID *ID)
154
155   void * result;
156   envelope *env = UsrToEnv(m);
157   int i = createFuture();
158   env->setRef(i);
159   CkSendMsg(ep, m, ID);
160   result = waitFuture(i, 1);
161   return (result);
162 }
163
164 class FutureBOC: public Group {
165 public:
166   FutureBOC(FutureInitMsg *m) { delete m; }
167   void SetFuture(FutureInitMsg * m) { 
168     int key;
169     key = UsrToEnv((void *)m)->getRef();
170     setFuture( key, m);
171   }
172 };
173
174 extern "C" 
175 void CkSendToFuture(int futNum, void *m, int PE)
176 {
177   UsrToEnv(m)->setRef(futNum);
178   fBOC.SetFuture((FutureInitMsg *)m,PE);
179 }
180
181 #include "CkFutures.def.h"