Changeset 75c668 in git
- Timestamp:
- Aug 14, 2012, 3:35:17 PM (12 years ago)
- Branches:
- (u'spielwiese', '17f1d200f27c5bd38f5dfc6e8a0879242279d1d8')
- Children:
- fc70ace7d1e2b805c813bfe25f3dc25f2670531a
- Parents:
- 971984cfbe4d595f6502922bcb6117ba46acd6d2
- git-author:
- Alexander Dreyer <alexander.dreyer@itwm.fraunhofer.de>2012-08-14 15:35:17+02:00
- git-committer:
- Oleksandr Motsak <motsak@mathematik.uni-kl.de>2012-09-05 15:52:15+02:00
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/countedref.cc
r971984c r75c668 33 33 34 34 35 class CountedRef { 36 typedef CountedRef self; 35 class CountedRefEnv { 36 typedef CountedRefEnv self; 37 38 39 40 }; 41 42 class RefCounter { 43 typedef RefCounter self; 44 45 /// Name numerical type for enumbering 46 typedef unsigned long count_type; 37 47 38 48 public: 39 typedef int id_type; 40 41 /// Set Singular type identitfier 42 CountedRef(blackbox& bbx) { 43 CountedRefAccess_id() = setBlackboxStuff(&bbx, "reference"); 44 } 45 CountedRef() { } 46 47 /// Get Singular type identitfier 48 static id_type id() { return CountedRefAccess_id(); } 49 50 /// Check for being reference in Singular interpreter object 51 static BOOLEAN is_ref(leftv arg) { return (arg->Typ() == id()); } 52 private: 53 /// Access identifier (one per class) 54 static id_type& CountedRefAccess_id() { 55 static id_type g_id = 0; 56 return g_id; 57 } 58 59 }; 60 /** @class CountedRefData 61 * This class stores a reference counter as well as a Singular interpreter object. 62 * 63 * It also stores the Singular token number, once per type. 64 **/ 65 class CountedRefData: public CountedRef { 66 typedef CountedRefData self; 67 68 /// Forbit copy construction and normal assignment 69 CountedRefData(const self&); 70 self& operator=(const self&); 71 72 public: 73 typedef unsigned long count_type; 74 75 /// Construct reference for Singular object 76 CountedRefData(leftv data): m_data(*data), m_count(0), m_ring(NULL) { 77 78 if (RingDependend(data->Typ()) && (currRing != NULL) ) { 79 m_ring = currRing; 80 ++m_ring->ref; 81 } 82 if (data->e) { 83 m_data.e = (Subexpr)omAlloc0Bin(sSubexpr_bin); 84 memcpy(m_data.e, data->e, sizeof(*m_data.e)); 85 } 86 } 49 /// Default Constructor 50 RefCounter(): m_count(0) {} 51 52 /// Copying resets the counter 53 RefCounter(const self& rhs): m_count(0) {} 87 54 88 55 /// Destructor 89 ~CountedRefData() { 90 assume(m_count == 0); 91 if (m_data.e) omFree(m_data.e); 92 if (m_ring) --m_ring->ref; 93 } 94 95 96 static BOOLEAN set_to(leftv res, void* data, int op) 97 { 98 if (res->rtyp == IDHDL) { 99 IDDATA((idhdl)res->data) = (char *)data; 100 IDTYP((idhdl)res->data) = op; 101 } 102 else { 103 res->data = (void *)data; 104 res->rtyp = op; 105 } 106 return (op == NONE? TRUE: FALSE); 107 } 108 109 static BOOLEAN construct(leftv result, leftv arg) { 110 self* pRef(is_ref(arg)? static_cast<self*>(arg->Data()): new self(arg)); 111 pRef->reclaim(); 112 113 return set_to(result, pRef, id()); 114 } 56 ~RefCounter() { assume(m_count == 0); } 115 57 116 58 /// @name Reference counter management … … 121 63 //@} 122 64 123 leftv get () { 124 leftv result = (leftv)omAlloc0(sizeof(sleftv)); 125 get(*result); 126 return result; 127 } 128 129 void get(sleftv& result) { 65 private: 66 /// Number of references 67 count_type m_count; 68 }; 69 70 class LeftvShallow { 71 typedef LeftvShallow self; 72 73 public: 74 LeftvShallow(leftv data): m_data(*data) { copy(&m_data.e, data->e); } 75 LeftvShallow(const self& rhs): m_data(rhs.m_data) { copy(&m_data.e, rhs.m_data.e); } 76 77 ~LeftvShallow() { kill(m_data.e); } 78 79 BOOLEAN get(leftv result) { 80 leftv next = result->next; 81 result->next = NULL; 82 result->CleanUp(); 83 memcpy(result, &m_data, sizeof(m_data)); 84 copy(&result->e, m_data.e); 85 result->next = next; 86 return FALSE; 87 } 88 89 /// Read-only access to object 90 const leftv operator->() { return &m_data; } 91 92 private: 93 static void copy(Subexpr* result, Subexpr rhs) { 94 for (Subexpr* current = result; rhs != NULL; 95 current = &(*current)->next, rhs = rhs->next) 96 *current = (Subexpr)memcpy(omAlloc0Bin(sSubexpr_bin), rhs, sizeof(*rhs)); 97 } 98 99 static void kill(Subexpr rhs) { 100 for (Subexpr next; rhs!=NULL; rhs = next, next = rhs->next) { 101 next = rhs->next; 102 omFree(rhs); 103 } 104 } 105 sleftv m_data; 106 }; 107 108 /** @class CountedRefData 109 * This class stores a reference counter as well as a Singular interpreter object. 110 * 111 * It also stores the Singular token number, once per type. 112 **/ 113 class CountedRefData: 114 public RefCounter { 115 typedef CountedRefData self; 116 typedef RefCounter base; 117 118 /// Forbit copy construction and normal assignment 119 CountedRefData(const self&); 120 self& operator=(const self&); 121 122 public: 123 /// Construct reference for Singular object 124 CountedRefData(leftv data): base(), m_data(data), m_ring(NULL) { 125 if (RingDependend(data->Typ()) && (currRing != NULL) ) { 126 m_ring = currRing; 127 ++m_ring->ref; 128 } 129 130 } 131 132 static idhdl* id_root; 133 134 /// Destructor 135 ~CountedRefData() { } 136 137 BOOLEAN get(leftv result) { 130 138 if (m_ring && (m_ring != currRing)) { 131 139 Werror("Can only use references from current ring."); 132 return ;140 return TRUE; 133 141 } 134 leftv next = result.next; 135 memcpy(&result, &m_data, sizeof(sleftv)); 136 result.next = next; 142 // dereferencing only makes sense, if something else points here, too. 143 assume(count() > 1); 144 return m_data.get(result); 145 } 146 147 LeftvShallow get() { 148 if (m_ring && (m_ring != currRing)) 149 Werror("Can only use references from current ring."); 150 151 return LeftvShallow(m_data); 137 152 } 138 153 139 154 private: 140 /// Reference counter141 count_type m_count;142 155 143 156 /// Singular object 144 sleftvm_data;157 LeftvShallow m_data; 145 158 146 159 /// Store ring for ring-dependent objects … … 148 161 }; 149 162 150 class CountedRefAccessBase { 151 typedef CountedRefAccessBase self; 152 153 public: 154 CountedRefAccessBase(leftv data): 155 m_data(data) {} 156 157 CountedRefAccessBase(const self& rhs): 158 m_data(rhs.m_data) {} 159 160 ~CountedRefAccessBase() {} 161 162 leftv operator->() { return *this; } 163 operator leftv() { return m_data; } 164 165 protected: 166 leftv m_data; 167 }; 168 169 170 class CountedRefAccess: 171 public CountedRefAccessBase { 172 typedef CountedRefAccess self; 173 typedef CountedRefAccessBase base; 174 175 public: 176 CountedRefAccess(CountedRefData* data): 177 m_owns(true), base(data->get()) { } 178 179 180 CountedRefAccess(leftv data): 181 m_owns(CountedRef::is_ref(data)), base(data) { 182 if (m_owns) m_data = static_cast<CountedRefData*>(data->Data())->get(); 163 /// blackbox support - initialization 164 /// @note deals as marker for compatible references, too. 165 void* countedref_Init(blackbox*) 166 { 167 return NULL; 168 } 169 170 class CountedRef { 171 typedef CountedRef self; 172 173 public: 174 /// name type for identifiers 175 typedef int id_type; 176 177 /// Name type for handling reference data 178 typedef CountedRefData data_type; 179 180 /// Check whether argument is already a reference type 181 static BOOLEAN is_ref(int typ) { 182 return ((typ > MAX_TOK) && 183 (getBlackboxStuff(typ)->blackbox_Init == countedref_Init)); 184 } 185 186 /// Construct reference data object from 187 static BOOLEAN construct(leftv result, leftv arg) { 188 data_type* data = (result->Typ() == arg->Typ()? 189 static_cast<data_type*>(arg->Data()): new data_type(arg)); 190 data->reclaim(); 191 if (result->rtyp == IDHDL) 192 IDDATA((idhdl)result->data) = (char *)data; 193 else 194 result->data = (void *)data; 195 return (data == NULL? TRUE: FALSE); 196 } 197 198 /// Kills the link to the referenced object 199 static void destruct(data_type* data) { 200 if(data && !data->release()) { 201 delete data; 183 202 } 184 185 CountedRefAccess(const self& rhs): 186 m_owns(rhs.m_owns), base(rhs) { 187 188 if (m_owns){ 189 m_data = (leftv)omAlloc0(sizeof(sleftv)); 190 if(rhs.m_data != NULL) memcpy(m_data, rhs.m_data, sizeof(sleftv)); 191 } 192 } 193 194 ~CountedRefAccess() { if (m_owns) omFree(m_data); } 195 196 private: 197 bool m_owns; 198 }; 199 200 class CountedRefCast: 201 public CountedRefAccessBase { 202 typedef CountedRefCast self; 203 typedef CountedRefAccessBase base; 204 public: 205 CountedRefCast(void* data): 206 base(static_cast<CountedRefData*>(data)->get()) { } 207 208 CountedRefCast(leftv data): 209 base(static_cast<CountedRefData*>(data->Data())->get()) { } 210 211 CountedRefCast(const self& rhs): 212 base((leftv)omAlloc0(sizeof(sleftv))) { 213 memcpy(m_data, rhs.m_data, sizeof(sleftv)); 214 } 215 216 ~CountedRefCast() { omFree(m_data); } 217 }; 218 219 /// blackbox support - initialization 220 void* countedref_Init(blackbox*) 221 { 222 return NULL; 223 } 203 } 204 205 /// Get the actual object 206 /// @note It may change leftv. It is common practice, so we are fine with it. 207 static BOOLEAN dereference(leftv arg) { 208 assume((arg != NULL) && is_ref(arg->Typ())); 209 do { 210 assume(arg->Data() != NULL); 211 data_type* data = static_cast<data_type*>(arg->Data()); 212 if(data->get(arg)) return TRUE; 213 } while (is_ref(arg->Typ())); 214 return resolve_tail(arg); 215 } 216 217 /// If necessary dereference. 218 /// @note The may change leftv. It is common practice, so we are fine with it. 219 static BOOLEAN resolve(leftv arg) { 220 assume(arg != NULL); 221 while (is_ref(arg->Typ())) { if(dereference(arg)) return TRUE; }; 222 return resolve_tail(arg); 223 } 224 225 private: 226 /// Dereference (is needed) subsequent objects of sequences 227 static BOOLEAN resolve_tail(leftv arg) { 228 for(leftv next = arg->next; next != NULL; next = next->next) 229 if(resolve(next)) 230 return TRUE; 231 return FALSE; 232 } 233 }; 224 234 225 235 /// blackbox support - convert to string representation 226 236 void countedref_Print(blackbox *b, void* ptr) 227 237 { 228 if (ptr != NULL) CountedRefCast(ptr)->Print();238 if (ptr != NULL) static_cast<CountedRefData*>(ptr)->get()->Print(); 229 239 } 230 240 … … 232 242 char* countedref_String(blackbox *b, void* ptr) 233 243 { 234 if (ptr != NULL) return CountedRefCast(ptr)->String();244 if (ptr != NULL) return static_cast<CountedRefData*>(ptr)->get()->String(); 235 245 } 236 246 … … 246 256 { 247 257 // Case: replace assignment behind reference 248 if (result->Data() != NULL) 249 return iiAssign(CountedRefCast(result), CountedRefAccess(arg)); 258 if (result->Data() != NULL) 259 return CountedRef::dereference(result) || CountedRef::resolve(arg) || 260 iiAssign(result, arg); 250 261 251 262 // Case: new reference 252 263 if(arg->rtyp == IDHDL) 253 return CountedRef Data::construct(result, arg);264 return CountedRef::construct(result, arg); 254 265 255 266 Werror("Can only take reference from identifier"); 256 return CountedRefData::set_to(result, NULL, NONE);267 return FALSE; 257 268 } 258 269 259 260 270 /// blackbox support - unary operations 261 271 BOOLEAN countedref_Op1(int op, leftv res, leftv head) 262 272 { 263 273 if(op == TYPEOF_CMD) 264 return CountedRefData::set_to(res, omStrDup("reference"), STRING_CMD); 265 266 CountedRefCast value(head); 267 if (op == DEF_CMD){ 268 res->rtyp = value->Typ(); 269 return iiAssign(res, value); 270 } 271 return iiExprArith1(res, value, op); 274 return blackboxDefaultOp1(op, res, head); 275 276 return CountedRef::dereference(head) || 277 iiExprArith1(res, head, (op == DEF_CMD? head->Typ(): op)); 272 278 } 273 279 … … 275 281 BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg) 276 282 { 277 return iiExprArith2(res, CountedRefCast(head), op, CountedRefAccess(arg)); 283 return CountedRef::dereference(head) || CountedRef::resolve(arg) || 284 iiExprArith2(res, head, op, arg); 278 285 } 279 286 … … 281 288 BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2) 282 289 { 283 return iiExprArith3(res, op, CountedRefCast(head), 284 CountedRefAccess(arg1), CountedRefAccess(arg2)); 290 return CountedRef::dereference(head) || 291 CountedRef::resolve(arg1) || CountedRef::resolve(arg2) || 292 iiExprArith3(res, op, head, arg1, arg2); 285 293 } 286 294 … … 289 297 BOOLEAN countedref_OpM(int op, leftv res, leftv args) 290 298 { 291 CountedRefCast value(args); 292 value->next = args->next; 293 for(leftv current = args->next; current != NULL; current = current->next) { 294 if(CountedRef::is_ref(current)) { 295 CountedRefData* pRef = static_cast<CountedRefData*>(current->Data()); 296 pRef->get(*current); 297 pRef->release(); 298 assume(pRef->count() > 0); 299 } 300 } 301 args->next = NULL; 302 303 return iiExprArithM(res, value, op); 299 return CountedRef::dereference(args) || iiExprArithM(res, args, op); 304 300 } 305 301 … … 307 303 void countedref_destroy(blackbox *b, void* ptr) 308 304 { 309 CountedRefData* pRef = static_cast<CountedRefData*>(ptr); 310 if(ptr && !pRef->release()) 311 delete pRef; 305 CountedRef::destruct(static_cast<CountedRefData*>(ptr)); 306 } 307 308 309 /// blackbox support - assign element 310 BOOLEAN countedref_AssignShared(leftv result, leftv arg) 311 { 312 // Case: replace assignment behind reference 313 if (result->Data() != NULL) 314 return CountedRef::dereference(result) || CountedRef::resolve(arg) || 315 iiAssign(result, arg); 316 317 318 if(CountedRef::resolve(arg)) 319 return TRUE; 320 321 char* name=(char*)omAlloc0(512); 322 static unsigned long counter = 0; 323 do { 324 sprintf(name, "_shareddata_%s_%s_%d\0", result->Name(), arg->Name(), ++counter); 325 } 326 while(ggetid(name)); 327 idhdl handle = enterid(name, 0, arg->Typ(), &IDROOT, FALSE); 328 omFree(name); 329 if (handle==NULL) { 330 Werror("Initializing shared failed"); 331 return TRUE; 332 } 333 334 IDDATA(handle) = (char*)arg->CopyD(); 335 arg->data = handle; 336 arg->rtyp = IDHDL; 337 338 return CountedRef::construct(result, arg); 339 } 340 341 /// blackbox support - destruction 342 void countedref_destroyShared(blackbox *b, void* ptr) 343 { 344 CountedRefData* data = static_cast<CountedRefData*>(ptr); 345 346 if(data && !data->release()) { 347 leftv tmp = (leftv) omAlloc0(sizeof(*tmp)); 348 data->get(tmp); 349 killid(IDID((idhdl)(tmp->data)), &IDROOT); 350 delete data; 351 } 352 312 353 } 313 354 … … 326 367 bbx->blackbox_OpM = countedref_OpM; 327 368 bbx->data = omAlloc0(newstruct_desc_size()); 328 CountedRef init(*bbx); 369 setBlackboxStuff(bbx, "reference"); 370 371 blackbox *bbxshared = 372 (blackbox*)memcpy(omAlloc(sizeof(blackbox)), bbx, sizeof(blackbox)); 373 bbxshared->blackbox_Assign = countedref_AssignShared; 374 bbxshared->blackbox_destroy = countedref_destroyShared; 375 setBlackboxStuff(bbxshared, "shared"); 329 376 } 330 377
Note: See TracChangeset
for help on using the changeset viewer.