00001
00002 #include <stdlib.h>
00003 #include <converse.h>
00004
00005 #define CmiAlloc malloc
00006 #define CmiFree free
00007
00008 typedef struct CmmEntryStruct *CmmEntry;
00009
00010 struct CmmEntryStruct
00011 {
00012 CmmEntry next;
00013 void *msg;
00014 int ntags;
00015 int tags[1];
00016 };
00017
00018 struct CmmTableStruct
00019 {
00020 CmmEntry first;
00021 CmmEntry *lasth;
00022 };
00023
00024
00025 CmmTable CmmNew(void)
00026 {
00027 CmmTable result = (CmmTable)CmiAlloc(sizeof(struct CmmTableStruct));
00028 result->first = 0;
00029 result->lasth = &(result->first);
00030 return result;
00031 }
00032
00033 void CmmFree(CmmTable t)
00034 {
00035 if (t==NULL) return;
00036 #if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
00037 if (t->first!=NULL) CmiAbort("Cannot free a non-empty message table!");
00038 #endif
00039 CmiFree(t);
00040 }
00041
00042
00043 void CmmFreeAll(CmmTable t){
00044 CmmEntry cur;
00045 if(t==NULL) return;
00046 cur = t->first;
00047 while(cur){
00048 CmmEntry toDel = cur;
00049 cur = cur->next;
00050 CmiFree(toDel);
00051 }
00052 }
00053
00054 void CmmPut(CmmTable t, int ntags, int *tags, void *msg)
00055 {
00056 int i;
00057 CmmEntry e=(CmmEntry)CmiAlloc(sizeof(struct CmmEntryStruct)+(ntags*sizeof(int)));
00058 e->next = 0;
00059 e->msg = msg;
00060 e->ntags = ntags;
00061 for (i=0; i<ntags; i++) e->tags[i] = tags[i];
00062 *(t->lasth) = e;
00063 t->lasth = &(e->next);
00064 }
00065
00066 static int CmmTagsMatch(int ntags1, int *tags1, int ntags2, int *tags2)
00067 {
00068 int ntags = ntags1;
00069 if (ntags1 != ntags2) return 0;
00070 while (1) {
00071 int tag1, tag2;
00072 if (ntags == 0) return 1;
00073 ntags--;
00074 tag1 = *tags1++;
00075 tag2 = *tags2++;
00076 if (tag1==tag2) continue;
00077 if (tag1==CmmWildCard) continue;
00078 if (tag2==CmmWildCard) continue;
00079 return 0;
00080 }
00081 }
00082
00083 void *CmmFind(CmmTable t, int ntags, int *tags, int *rtags, int del)
00084 {
00085 CmmEntry *enth; CmmEntry ent; void *msg; int i;
00086
00087
00088 if(t==NULL) return NULL;
00089
00090 enth = &(t->first);
00091 while (1) {
00092 ent = (*enth);
00093 if (ent==0) return 0;
00094 if (CmmTagsMatch(ntags, tags, ent->ntags, ent->tags)) {
00095 if (rtags) for (i=0; i<ntags; i++) rtags[i] = ent->tags[i];
00096 msg = ent->msg;
00097 if (del) {
00098 CmmEntry next = ent->next;
00099 (*enth) = next;
00100 if (next == 0) t->lasth = enth;
00101 CmiFree(ent);
00102 }
00103 return msg;
00104 }
00105 enth = &(ent->next);
00106 }
00107 }
00108
00109
00110 int CmmGetLastTag(CmmTable t, int ntags, int* tags)
00111 {
00112 CmmEntry *enth; CmmEntry ent;
00113 enth = &(t->first);
00114 while (1) {
00115 ent = (*enth);
00116 if (ent==0) return -1;
00117 if (CmmTagsMatch(ntags, tags, ntags, ent->tags)) {
00118 return (ent->tags[ent->ntags-1]);
00119 }
00120 enth = &(ent->next);
00121 }
00122 return -1;
00123 }
00124
00125 int CmmEntries(CmmTable t)
00126 {
00127 int n = 0;
00128 CmmEntry e = t->first;
00129 while (e) {
00130 e = e->next;
00131 n++;
00132 }
00133 return n;
00134 }
00135
00136
00137 CmmTable CmmPup(pup_er p, CmmTable t, CmmPupMessageFn msgpup)
00138 {
00139 int nentries;
00140
00141 if(!pup_isUnpacking(p))
00142 {
00143 CmmEntry e = t->first, doomed;
00144 nentries = CmmEntries(t);
00145 pup_int(p, &nentries);
00146 while(e) {
00147 pup_int(p, &(e->ntags));
00148 pup_ints(p, e->tags, e->ntags);
00149 msgpup(p,&e->msg);
00150 doomed=e;
00151 e = e->next;
00152 if (pup_isDeleting(p))
00153 CmiFree(doomed);
00154 }
00155 if(pup_isDeleting(p))
00156 {
00157 t->first=NULL;
00158 CmmFree(t);
00159 return 0;
00160 } else
00161 return t;
00162 }
00163 if(pup_isUnpacking(p))
00164 {
00165 int i;
00166 t = CmmNew();
00167 pup_int(p, &nentries);
00168 for(i=0;i<nentries;i++)
00169 {
00170 int ntags, *tags;
00171 void *msg;
00172 pup_int(p, &ntags);
00173 tags = (int*) malloc(ntags*sizeof(int));
00174 pup_ints(p, tags, ntags);
00175 msgpup(p,&msg);
00176 CmmPut(t, ntags, tags, msg);
00177 free(tags);
00178 }
00179 return t;
00180 }
00181 return NULL;
00182 }
00183