Changeset cda275f in git
- Timestamp:
- Sep 5, 2012, 3:25:07 PM (10 years ago)
- Branches:
- (u'jengelh-datetime', 'ceac47cbc86fe4a15902392bdbb9bd2ae0ea02c6')(u'spielwiese', 'ad2543eab51733612ba7d118afc77edca719600e')
- Children:
- 88180dcbe2ead266f3547e207fd8b7d03a0b9f1e
- Parents:
- e318c0df53d14d067ee1ee383417566c2e226e9b
- git-author:
- Alexander Dreyer <alexander.dreyer@itwm.fraunhofer.de>2012-09-05 15:25:07+02:00
- git-committer:
- Oleksandr Motsak <motsak@mathematik.uni-kl.de>2012-09-05 15:52:17+02:00
- Location:
- Singular
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/countedref.cc
re318c0 rcda275f 1 // /-*- c++ -*-1 // -*- c++ -*- 2 2 //***************************************************************************** 3 3 /** @file countedref.cc … … 17 17 18 18 19 20 #include <Singular/mod2.h> 21 22 #include <Singular/ipid.h> 23 #include <Singular/blackbox.h> 24 #include <Singular/newstruct.h> 25 26 #include <omalloc/omalloc.h> 27 #include <kernel/febase.h> 28 #include <kernel/longrat.h> 29 #include <Singular/subexpr.h> 30 #include <Singular/ipshell.h> 31 32 #include "lists.h" 33 #include "attrib.h" 19 #include "mod2.h" 20 #include "ipid.h" 34 21 35 22 #include "countedref.h" 36 23 37 #if 0 38 /** @class CountedRefPtr 39 * This class implements a smart pointer which handles pointer-style access 40 * to a reference-counted structure and destructing the latter after use. 41 * 42 * The template arguments, include the pointer type @c PtrType, and two 43 * integral (bool) properties: use @c isWeak to disallow destruction 44 * and @c NeverNull to assume, that @c PtrType cannot be @c NULL. 45 * Finally, @c CountType allows you to select a typ to represent the internal reference count. 46 * 47 * @note The class of @c PtrType must have an accessible integral attribute @c ref. 48 * For convenience use @c RefCounter as public base. 49 * In addition you must overload @c void CountedRefPtr_kill(PtrType) accordingly. 50 **/ 51 template <class PtrType, bool isWeak = false, bool NeverNull = false, class CountType = short> 52 class CountedRefPtr { 53 typedef CountedRefPtr self; 54 55 public: 56 //{ @name Name template arguments 57 typedef PtrType ptr_type; 58 typedef CountType count_type; 59 enum { is_weak = isWeak, never_null = NeverNull }; 60 //} 61 62 /// Default constructor @note: exisis only if @c NeverNull is false 63 CountedRefPtr(): m_ptr(NULL) {} 64 65 /// Convert from pointer 66 CountedRefPtr(ptr_type ptr): m_ptr(ptr) { reclaim(); } 67 68 /// Convert from compatible smart pointer 69 template <bool Never> 70 CountedRefPtr(const CountedRefPtr<ptr_type, !is_weak, Never, count_type>& rhs): 71 m_ptr(rhs.m_ptr) { reclaim(); } 72 73 /// Construct refernce copy 74 CountedRefPtr(const self& rhs): 75 m_ptr(rhs.m_ptr) { reclaim(); } 76 77 /// Unlink one reference 78 ~CountedRefPtr() { release(); } 79 80 //{ @name Replace data behind reference 81 self& operator=(const self& rhs) { return operator=(rhs.m_ptr); } 82 self& operator=(ptr_type ptr) { 83 release(); 84 m_ptr = ptr; 85 reclaim(); 86 return *this; 87 } 88 //} 89 90 /// Checking equality 91 bool operator==(const self& rhs) const { return m_ptr == rhs.m_ptr; } 92 93 //{ @name Pointer-style interface 94 bool operator==(ptr_type ptr) const { return m_ptr == ptr; } 95 operator bool() const { return NeverNull || m_ptr; } 96 operator const ptr_type() const { return m_ptr; } 97 operator ptr_type() { return m_ptr; } 98 const ptr_type operator->() const { return *this; } 99 ptr_type operator->() { return *this; } 100 //} 101 102 //{ @name Reference count interface 103 count_type count() const { return (*this? m_ptr->ref: 0); } 104 void reclaim() { if (*this) ++m_ptr->ref; } 105 void release() { 106 if (*this && (--m_ptr->ref <= 0) && !is_weak) 107 CountedRefPtr_kill(m_ptr); 108 } 109 //} 110 111 private: 112 /// Store actual pointer 113 ptr_type m_ptr; 114 }; 115 116 /// Default constructor only implemented if @c NeverNull is false 117 //template <class PtrType, bool isWeak,bool val,class CountType> 118 //inline CountedRefPtr<PtrType, isWeak, val, CountType>::CountedRefPtr(): 119 // m_ptr(NULL) { } 120 121 /** @class RefCounter 122 * This class implements implements a refernce counter which we can use 123 * as a public base of objects managed by @CountedRefPtr. 124 **/ 125 class RefCounter { 126 127 public: 128 /// Name numerical type for enumbering 129 typedef short count_type; 130 131 /// Allow our smart pointer to access internals 132 template <class, bool, bool, class> friend class CountedRefPtr; 133 134 /// Any Constructor resets the counter 135 RefCounter(...): ref(0) {} 136 137 /// Destructor 138 ~RefCounter() { assume(ref == 0); } 139 140 private: 141 /// Number of references 142 count_type ref; // naming consistent with other classes 143 }; 144 #endif 24 #include "blackbox.h" 25 #include "newstruct.h" 26 #include "ipshell.h" 27 145 28 class CountedRefEnv { 146 29 typedef CountedRefEnv self; 147 30 148 31 public: 149 static leftv idify(leftv head, idhdl* root) { 150 idhdl handle = newid(head, root); 151 leftv res = (leftv)omAlloc0(sizeof(*res)); 152 res->data =(void*) handle; 153 res->rtyp = IDHDL; 154 return res; 155 } 156 157 static idhdl newid(leftv head, idhdl* root) { 158 159 static unsigned int counter = 0; 160 char* name = (char*) omAlloc0(512); 161 sprintf(name, " :%u:%p:_shared_: ", ++counter, head->data); 162 if ((*root) == NULL ) 163 enterid(name, 0, head->rtyp, root, TRUE, FALSE); 164 else 165 *root = (*root)->set(name, 0, head->rtyp, TRUE); 166 167 IDDATA(*root) = (char*) head->data; 168 return *root; 169 } 170 171 static void clearid(idhdl handle, idhdl* root) { 172 IDDATA(handle)=NULL; 173 IDTYP(handle)=NONE; 174 killhdl2(handle, root, NULL); 175 } 32 176 33 static int& ref_id() { 177 34 static int g_ref_id = 0; … … 185 42 }; 186 43 187 #if 0188 44 /// Overloading ring destruction 189 45 inline void CountedRefPtr_kill(ring r) { rKill(r); } 190 class LeftvHelper { 191 public: 192 template <class Type> 193 static Type* cpy(Type* result, Type* data) { 194 return (Type*)memcpy(result, data, sizeof(Type)); 195 } 196 template <class Type> 197 static Type* cpy(Type* data) { 198 return cpy((Type*)omAlloc0(sizeof(Type)), data); 199 } 200 template <class Type> 201 static Type* recursivecpy(Type* data) { 202 if (data == NULL) return data; 203 Type* result = cpy(data); 204 result->next = recursivecpy(data->next); 205 return result; 206 } 207 template <class Type> 208 static Type* shallowcpy(Type* result, Type* data) { 209 cpy(result, data)->e = recursivecpy(data->e); 210 return result; 211 } 212 template <class Type> 213 static Type* shallowcpy(Type* data) { 214 return shallowcpy((Type*) omAlloc0(sizeof(Type)), data); 215 } 216 template <class Type> 217 static void recursivekill(Type* current) { 218 if(current == NULL) return; 219 recursivekill(current->next); 220 omFree(current); 221 } 222 static leftv allocate() { return (leftv)omAlloc0(sizeof(sleftv)); } 223 224 }; 225 226 class LeftvShallow: 227 public LeftvHelper { 228 typedef LeftvShallow self; 229 230 public: 231 LeftvShallow(): m_data(allocate()) { } 232 LeftvShallow(leftv data): m_data(shallowcpy(data)) { } 233 LeftvShallow(const self& rhs): m_data(shallowcpy(rhs.m_data)) { } 234 235 ~LeftvShallow() { 236 recursivekill(m_data->e); 237 omFree(m_data); 238 } 239 self& operator=(leftv rhs) { 240 recursivekill(m_data->e); 241 shallowcpy(m_data, rhs); 242 return *this; 243 } 244 245 self& operator=(const self& rhs) { return (*this) = rhs.m_data; } 246 247 /// Access to object 248 const leftv operator->() const { return m_data; } 249 leftv operator->() { return m_data; } 250 251 protected: 252 leftv m_data; 253 }; 254 255 256 class LeftvDeep: public LeftvHelper { 257 typedef LeftvDeep self; 258 259 /// @name Do not permit copying 260 //@{ 261 self& operator=(const self&); 262 LeftvDeep(const self&); 263 //@} 264 265 public: 266 struct copy_tag {}; 267 LeftvDeep(): m_data(allocate()) {} 268 LeftvDeep(leftv data): m_data(cpy(data)) { 269 data->e = NULL; // occupy subexpression 270 if(!isid()) m_data->data=data->CopyD(); 271 } 272 273 LeftvDeep(leftv data, copy_tag): m_data(allocate()) { m_data->Copy(data); } 274 275 ~LeftvDeep() { m_data->CleanUp(); } 276 operator LeftvShallow() { return m_data;} 277 278 bool like(const self& rhs) const { return m_data->data == rhs.m_data->data; } 279 280 self& operator=(leftv rhs) { 281 if(isid()) { 282 m_data->e = rhs->e; 283 rhs->e = NULL; 284 IDTYP((idhdl)m_data->data) = rhs->Typ(); 285 IDDATA((idhdl)m_data->data) = (char*) rhs->CopyD(); 286 } 287 else { 288 m_data->CleanUp(); 289 m_data->Copy(rhs); 290 } 291 return *this; 292 } 293 294 /// Check a given context for our identifier 295 BOOLEAN brokenid(idhdl context) const { 296 assume(isid()); 297 return (context == NULL) || 298 ((context != (idhdl) m_data->data) && brokenid(IDNEXT(context))); 299 } 300 301 /// Put a shallow copy to given @c leftv 302 BOOLEAN put(leftv result) { 303 leftv next = result->next; 304 result->next = NULL; 305 result->CleanUp(); 306 307 shallowcpy(result, m_data); 308 result->next = next; 309 return FALSE; 310 } 311 312 /// Get additional data (e.g. subexpression data) from likewise instances 313 BOOLEAN retrieve(leftv res) { 314 if (res->data == m_data->data) { 315 if(m_data->e != res->e) recursivekill(m_data->e); 316 cpy(m_data, res); 317 res->Init(); 318 return TRUE; 319 } 320 return FALSE; 321 } 322 323 324 325 BOOLEAN isid() const { return m_data->rtyp==IDHDL;} 326 BOOLEAN ringed() { return m_data->RingDependend(); } 327 BOOLEAN unassigned() const { return m_data->Typ()==0; } 328 329 leftv idify(idhdl* root) { 330 leftv res = (isid()? m_data: CountedRefEnv::idify(m_data, root)); 331 ++(((idhdl)res->data)->ref); 332 return res; 333 } 334 335 336 void clearid(idhdl* root) { 337 assume(isid()); 338 if (--((idhdl)m_data->data)->ref <= 0) // clear only if we own 339 CountedRefEnv::clearid((idhdl)m_data->data, root); 340 } 341 342 private: 343 leftv m_data; 344 }; 345 #endif 46 47 346 48 /** @class CountedRefData 347 49 * This class stores a reference counter as well as a Singular interpreter object. 348 * 349 * It also stores the Singular token number, once per type. 50 * It also take care of the context, e.g. the current ring, indexed object, etc. 350 51 **/ 351 52 class CountedRefData: 352 53 public RefCounter { 353 54 typedef CountedRefData self; 55 public: 354 56 typedef CountedRefWeakPtr<self*> back_ptr; 57 private: 355 58 typedef RefCounter base; 356 59 … … 758 461 CountedRefShared(const base& rhs): base(rhs) { } 759 462 760 /// Gen reate463 /// Generate from data pointer 761 464 CountedRefShared(data_ptr rhs): base(rhs) { } 762 465 … … 787 490 /// Temporarily wrap with identifier for '[' and '.' operation 788 491 self subscripted() { return self(m_data->subscripted()); } 492 493 /// 494 data_type::back_ptr weakref() { return m_data->weakref(); } 789 495 790 496 BOOLEAN retrieve(leftv res, int typ) { … … 897 603 } 898 604 605 606 BOOLEAN countedref_serialize(blackbox *b, void *d, si_link f) 607 { 608 sleftv l; 609 memset(&l,0,sizeof(l)); 610 l.rtyp = STRING_CMD; 611 l.data = (void*)omStrDup("shared"); // references are converted 612 f->m->Write(f, &l); 613 CountedRefShared::cast(d).dereference(&l); 614 f->m->Write(f, &l); 615 return FALSE; 616 } 617 618 BOOLEAN countedref_deserialize(blackbox **b, void **d, si_link f) 619 { 620 // rtyp must be set correctly (to the blackbox id) by routine calling 621 leftv data=f->m->Read(f); 622 CountedRefShared sh(data); 623 *d = sh.outcast(); 624 return FALSE; 625 } 626 899 627 void countedref_init() 900 628 { … … 910 638 bbx->blackbox_Op3 = countedref_Op3; 911 639 bbx->blackbox_OpM = countedref_OpM; 640 bbx->blackbox_serialize = countedref_serialize; 641 bbx->blackbox_deserialize = countedref_deserialize; 912 642 bbx->data = omAlloc0(newstruct_desc_size()); 913 643 CountedRefEnv::ref_id()=setBlackboxStuff(bbx, "reference"); -
Singular/countedref.h
re318c0 rcda275f 20 20 #ifndef SINGULAR_COUNTEDREF_H_ 21 21 #define SINGULAR_COUNTEDREF_H_ 22 23 #include <omalloc/omalloc.h> 24 #include <kernel/structs.h> 25 #include <kernel/febase.h> 22 26 23 27 /** @class CountedRefPtr … … 101 105 }; 102 106 103 /// Default constructor only implemented if @c NeverNull is false104 //template <class PtrType, bool isWeak,bool val,class CountType>105 //inline CountedRefPtr<PtrType, isWeak, val, CountType>::CountedRefPtr():106 // m_ptr(NULL) { }107 108 107 /** @class RefCounter 109 108 * This class implements implements a refernce counter which we can use … … 139 138 public: 140 139 friend class CountedRefWeakPtr<PtrType>; 140 ~CountedRefIndirectPtr() { } 141 141 142 private: 142 143 CountedRefIndirectPtr(PtrType ptr): m_ptr(ptr) { } 143 144 CountedRefIndirectPtr& operator=(PtrType ptr) { m_ptr = ptr; return *this; } 145 144 146 PtrType m_ptr; 145 147 }; … … 177 179 /// Test whether reference was never used 178 180 bool unassigned() const { return !m_indirect; } 179 180 181 /// Pointer-style interface 181 182 //@{ 182 183 operator bool() const { return operator->(); } 183 184 self& operator=(const self& rhs) { 184 m_indirect = rhs ;185 m_indirect = rhs.m_indirect; 185 186 return *this; 186 187 } … … 192 193 return *this; 193 194 } 194 bool operator==(ptr_type ptr) const { 195 return m_indirect &&(m_indirect->m_ptr == ptr); 195 bool operator==(ptr_type ptr) const { 196 return m_indirect &&(m_indirect->m_ptr == ptr); 196 197 } 197 198 bool operator!=(ptr_type rhs) const { return !operator==(rhs); } … … 199 200 ptr_type operator->() { return (m_indirect? m_indirect->m_ptr:NULL); } 200 201 //@} 201 202 202 private: 203 203 ptrptr_type m_indirect; 204 204 }; 205 206 205 207 206 … … 275 274 }; 276 275 276 /** @class LeftvShallow 277 * Ths class wraps @c leftv by taking into acount memory allocation, destruction 278 * as well as shallowly copying of a given @c leftv, i.e. we just copy auxiliary 279 * information (like subexpressions), but not the actual data. 280 * 281 * @note This is useful to avoid invalidating @c leftv while operating on th 282 **/ 277 283 class LeftvShallow: 278 284 public LeftvHelper { … … 280 286 281 287 public: 288 /// Just allocate (all-zero) @c leftv 282 289 LeftvShallow(): m_data(allocate()) { } 290 /// Shallow copy the input data 283 291 LeftvShallow(leftv data): m_data(shallowcpy(data)) { } 292 /// Construct (shallow) copy of @c *this 284 293 LeftvShallow(const self& rhs): m_data(shallowcpy(rhs.m_data)) { } 285 294 295 /// Destruct 286 296 ~LeftvShallow() { 287 297 recursivekill(m_data->e); 288 298 omFree(m_data); 289 299 } 300 301 /// Assign shallow copy of the input 290 302 self& operator=(leftv rhs) { 291 303 recursivekill(m_data->e); … … 293 305 return *this; 294 306 } 295 307 /// Assign (shallow) copy of @c *this 296 308 self& operator=(const self& rhs) { return (*this) = rhs.m_data; } 297 309 298 /// Access to object 310 /// @name Pointer-style access 311 //@{ 299 312 const leftv operator->() const { return m_data; } 300 313 leftv operator->() { return m_data; } 314 //@] 301 315 302 316 protected: 317 /// The actual data pointer 303 318 leftv m_data; 304 319 }; 305 320 306 307 class LeftvDeep: public LeftvHelper { 321 /** @class LeftvDeep 322 * This class wraps @c leftv by taking into acount memory allocation, destruction 323 * as well as deeply copying of a given @c leftv, i.e. we also take over 324 * ownership of the @c leftv data. 325 * 326 * We have two variants: 327 + LeftvDeep(leftv): treats referenced identifiers as "the data" 328 + LeftvDeep(leftv, copy_tag): takes care of a full copy of identifier's data 329 * 330 * @note It invalidats @c leftv on input. 331 **/ 332 class LeftvDeep: 333 public LeftvHelper { 308 334 typedef LeftvDeep self; 309 335 310 /// @name Do not permit copying 336 /// @name Do not permit copying (avoid inconsistence) 311 337 //@{ 312 338 self& operator=(const self&); … … 315 341 316 342 public: 317 struct copy_tag {};343 /// Allocate all-zero object by default 318 344 LeftvDeep(): m_data(allocate()) {} 345 346 /// Store a deep copy of the data 347 /// @ note Occupies the provided @c leftv and invalidates the latter 319 348 LeftvDeep(leftv data): m_data(cpy(data)) { 320 349 data->e = NULL; // occupy subexpression … … 322 351 } 323 352 353 /// Construct even deeper copy: 354 /// Skip identifier (if any) and take care of the data on our own 355 struct copy_tag {}; 324 356 LeftvDeep(leftv data, copy_tag): m_data(allocate()) { m_data->Copy(data); } 325 357 358 /// Really clear data 326 359 ~LeftvDeep() { m_data->CleanUp(); } 327 operator LeftvShallow() { return m_data;} 328 360 361 /// @name Access via shallow copy to avoid invalidating the stored handle 362 //@{ 363 operator LeftvShallow() { return m_data; } 364 LeftvShallow operator*() {return *this; } 365 //@} 366 367 /// Determine whether we point to the same data 329 368 bool like(const self& rhs) const { return m_data->data == rhs.m_data->data; } 330 369 370 /// Reassign a new deep copy by occupieing another @c leftv 371 /// @note clears @c *this in the first 331 372 self& operator=(leftv rhs) { 332 373 if(isid()) { … … 373 414 374 415 375 416 /// Check for being an identifier 376 417 BOOLEAN isid() const { return m_data->rtyp==IDHDL;} 418 /// Test whether we reference to ring-dependent data 377 419 BOOLEAN ringed() { return m_data->RingDependend(); } 420 /// Check whether (all-zero) initialized data was never assigned. 378 421 BOOLEAN unassigned() const { return m_data->Typ()==0; } 379 422 423 /// Wrap data by identifier, if not done yet 380 424 leftv idify(idhdl* root) { 381 425 leftv res = (isid()? m_data: LeftvHelper::idify(m_data, root)); … … 384 428 } 385 429 386 430 /// Erase identifier handles by @c *this 431 /// @note Assumes that we reference an identifier and that we own the latter. 432 /// This is useful to clear the result of a subsequent call of @c idify. 387 433 void clearid(idhdl* root) { 388 434 assume(isid()); … … 392 438 393 439 private: 440 /// Store the actual data 394 441 leftv m_data; 395 442 };
Note: See TracChangeset
for help on using the changeset viewer.