Removed almost all warnings on origin2000.
[charm.git] / src / conv-core / futures.c
1 #include "converse.h"
2
3 typedef struct Cfuture_data_s
4 {
5   void      *value;
6   int        ready;
7   CthThread  waiters;
8 }
9 *futdata;
10
11 typedef struct CfutureValue_s
12 {
13   char core[CmiMsgHeaderSizeBytes];
14   struct Cfuture_data_s *data;
15   int valsize;
16   double rest[1];
17 }
18 *CfutureValue;
19
20 #define field_offset(t, f) ((CMK_SIZE_T)(((t)0)->f))
21 #define void_to_value(v) ((CfutureValue)(((char*)v)-field_offset(CfutureValue,rest)))
22
23 CpvDeclare(int, CfutureStoreIndex);
24
25 Cfuture CfutureCreate()
26 {
27   futdata data = (futdata)malloc(sizeof(struct Cfuture_data_s));
28   Cfuture result;
29   data->value = 0;
30   data->ready = 0;
31   data->waiters = 0;
32   result.pe = CmiMyPe();
33   result.data = data;
34   return result;
35 }
36
37 static void CfutureAwaken(futdata data, CfutureValue val)
38 {
39   CthThread t;
40   data->value = val;
41   data->ready = 1;
42   for (t=data->waiters; t; t=CthGetNext(t))
43     CthAwaken(t);
44   data->waiters=0;
45 }
46
47 static void CfutureStore(CfutureValue m)
48 {
49   CmiGrabBuffer((void **)&m);
50   CfutureAwaken(m->data, m);
51 }
52
53 void *CfutureCreateBuffer(int bytes)
54 {
55   int valsize = sizeof(struct CfutureValue_s) + bytes;
56   CfutureValue m = (CfutureValue)CmiAlloc(valsize);
57   CmiSetHandler(m, CpvAccess(CfutureStoreIndex));
58   m->valsize = valsize;
59   return (void*)(m->rest);
60 }
61
62 void CfutureDestroyBuffer(void *v)
63 {
64   CmiFree(v);
65 }
66
67 void CfutureStoreBuffer(Cfuture f, void *value)
68 {
69   CfutureValue m = void_to_value(value);
70   if (f.pe == CmiMyPe()) {
71     CfutureAwaken(f.data, m);
72   } else {
73     m->data = f.data;
74     CmiSyncSendAndFree(f.pe, m->valsize, m);
75   }
76 }
77
78 void CfutureSet(Cfuture f, void *value, int len)
79 {
80   void *copy = CfutureCreateBuffer(len);
81   memcpy(copy, value, len);
82   CfutureStoreBuffer(f, copy);
83 }
84
85 void *CfutureWait(Cfuture f)
86 {
87   CthThread self; CfutureValue value; futdata data;
88   if (f.pe != CmiMyPe()) {
89     CmiPrintf("error: CfutureWait: future not local.\n");
90     exit(1);
91   }
92   data = f.data;
93   if (data->ready == 0) {
94     self = CthSelf();
95     CthSetNext(self, data->waiters);
96     data->waiters = self;
97     CthSuspend();
98   }
99   value = data->value;
100   return (void*)(value->rest);
101 }
102
103 void CfutureDestroy(Cfuture f)
104 {
105   if (f.pe != CmiMyPe()) {
106     CmiPrintf("error: CfutureDestroy: future not local.\n");
107     exit(1);
108   }
109   if (f.data->waiters) {
110     CmiPrintf("error: CfutureDestroy: destroying an active future.\n");
111     exit(1);
112   }
113   if (f.data->value) CmiFree(f.data->value);
114   free(f.data);
115 }
116
117 void CfutureModuleInit()
118 {
119   CpvInitialize(int, CfutureStoreIndex);
120   CpvAccess(CfutureStoreIndex) = CmiRegisterHandler(CfutureStore);
121 }