Added checking for null pointer returned by every malloc and new.
[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   _MEMCHECK(data);
30   data->value = 0;
31   data->ready = 0;
32   data->waiters = 0;
33   result.pe = CmiMyPe();
34   result.data = data;
35   return result;
36 }
37
38 static void CfutureAwaken(futdata data, CfutureValue val)
39 {
40   CthThread t;
41   data->value = val;
42   data->ready = 1;
43   for (t=data->waiters; t; t=CthGetNext(t))
44     CthAwaken(t);
45   data->waiters=0;
46 }
47
48 static void CfutureStore(CfutureValue m)
49 {
50   CmiGrabBuffer((void **)&m);
51   CfutureAwaken(m->data, m);
52 }
53
54 void *CfutureCreateBuffer(int bytes)
55 {
56   int valsize = sizeof(struct CfutureValue_s) + bytes;
57   CfutureValue m = (CfutureValue)CmiAlloc(valsize);
58   CmiSetHandler(m, CpvAccess(CfutureStoreIndex));
59   m->valsize = valsize;
60   return (void*)(m->rest);
61 }
62
63 void CfutureDestroyBuffer(void *v)
64 {
65   CmiFree(v);
66 }
67
68 void CfutureStoreBuffer(Cfuture f, void *value)
69 {
70   CfutureValue m = void_to_value(value);
71   if (f.pe == CmiMyPe()) {
72     CfutureAwaken(f.data, m);
73   } else {
74     m->data = f.data;
75     CmiSyncSendAndFree(f.pe, m->valsize, m);
76   }
77 }
78
79 void CfutureSet(Cfuture f, void *value, int len)
80 {
81   void *copy = CfutureCreateBuffer(len);
82   memcpy(copy, value, len);
83   CfutureStoreBuffer(f, copy);
84 }
85
86 void *CfutureWait(Cfuture f)
87 {
88   CthThread self; CfutureValue value; futdata data;
89   if (f.pe != CmiMyPe()) {
90     CmiPrintf("error: CfutureWait: future not local.\n");
91     exit(1);
92   }
93   data = f.data;
94   if (data->ready == 0) {
95     self = CthSelf();
96     CthSetNext(self, data->waiters);
97     data->waiters = self;
98     CthSuspend();
99   }
100   value = data->value;
101   return (void*)(value->rest);
102 }
103
104 void CfutureDestroy(Cfuture f)
105 {
106   if (f.pe != CmiMyPe()) {
107     CmiPrintf("error: CfutureDestroy: future not local.\n");
108     exit(1);
109   }
110   if (f.data->waiters) {
111     CmiPrintf("error: CfutureDestroy: destroying an active future.\n");
112     exit(1);
113   }
114   if (f.data->value) CmiFree(f.data->value);
115   free(f.data);
116 }
117
118 void CfutureModuleInit()
119 {
120   CpvInitialize(int, CfutureStoreIndex);
121   CpvAccess(CfutureStoreIndex) = CmiRegisterHandler(CfutureStore);
122 }