Changeset fc70ac in git


Ignore:
Timestamp:
Aug 17, 2012, 3:23:05 PM (10 years ago)
Author:
Alexander Dreyer <alexander.dreyer@…>
Branches:
(u'jengelh-datetime', 'ceac47cbc86fe4a15902392bdbb9bd2ae0ea02c6')(u'spielwiese', '1d362c315e551a5b527ab0759f8839cf0e94f3a5')
Children:
d2a236583625dd880d06a25cf10d02aefee3ba89
Parents:
75c6680561e0d1daedacd0b1599765c4061fe56d
git-author:
Alexander Dreyer <alexander.dreyer@itwm.fraunhofer.de>2012-08-17 15:23:05+02:00
git-committer:
Oleksandr Motsak <motsak@mathematik.uni-kl.de>2012-09-05 15:52:15+02:00
Message:
Treating subscriptable objects

fix: 'shared' of subscriptable types
new: reference counting rings here
chg: classes for LeftvDeep/Shallow
chg: Using class for construction
fix: got reference counts right
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Singular/countedref.cc

    r75c668 rfc70ac  
    3939
    4040};
     41idhdl* getmyroot() {
     42  static idhdl myroot = NULL;
     43  if (myroot == NULL) {
     44    myroot = enterid(" _shared_data_ ", 0, PACKAGE_CMD, &IDROOT, TRUE);
     45  }
     46  return &myroot;
     47}
    4148
    4249class RefCounter {
     
    5158
    5259  /// Copying resets the counter
    53   RefCounter(const self& rhs): m_count(0) {}
     60  RefCounter(const self&): m_count(0) {}
    5461
    5562  /// Destructor
     
    7077class LeftvShallow {
    7178  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); }
     79 
     80public:
     81  LeftvShallow(): m_data(allocate()) { }
     82  LeftvShallow(leftv data):
     83    m_data(init(allocate(), data)) { }
     84  LeftvShallow(const self& rhs):
     85    m_data(init(allocate(), rhs.m_data)) { }
     86
     87  ~LeftvShallow() { 
     88    kill();
     89    omFree(m_data);
     90  }
     91  self& operator=(leftv rhs) {
     92    kill();
     93    init(m_data, rhs);
     94    return *this;
     95  }
     96
     97  self& operator=(const self& rhs) { return (*this) = rhs.m_data; }
    7898
    7999  BOOLEAN get(leftv result) {
     
    81101    result->next = NULL;
    82102    result->CleanUp();
    83     memcpy(result, &m_data, sizeof(m_data));
    84     copy(&result->e, m_data.e);
     103    init(result, m_data);
    85104    result->next = next;
    86105    return FALSE;
    87106  }
    88107
    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 };
     108  /// Access to object
     109  leftv operator->() { return m_data;  }
     110
     111protected:
     112  static leftv allocate() { return (leftv)omAlloc0(sizeof(sleftv)); }
     113  static leftv init(leftv result, leftv data) {
     114    memcpy(result, data, sizeof(sleftv));
     115    copy(result->e, data->e);
     116    result-> next = NULL;
     117    return result;
     118  }
     119  static void copy(Subexpr& current, Subexpr rhs)  {
     120    if (rhs == NULL) return;
     121    current = (Subexpr)memcpy(omAlloc0Bin(sSubexpr_bin), rhs, sizeof(*rhs));
     122    copy(current->next, rhs->next);
     123  }
     124  void kill() { kill(m_data->e); }
     125  static void kill(Subexpr current) {
     126    if(current == NULL) return;
     127    kill(current->next);
     128    omFree(current);
     129  }
     130protected:
     131  leftv m_data;
     132};
     133
     134
     135class LeftvDeep:
     136  public LeftvShallow {
     137  typedef LeftvDeep self;
     138  typedef LeftvShallow base;
     139
     140public:
     141  LeftvDeep(): base() {}
     142  LeftvDeep(leftv data): base(data) { }
     143  LeftvDeep(const self& rhs): base(rhs) { }
     144
     145  ~LeftvDeep() { m_data->CleanUp(); }
     146
     147  self& operator=(const self& rhs) { return operator=(rhs.m_data); }
     148  self& operator=(leftv rhs) {
     149    m_data->CleanUp();
     150    m_data->Copy(rhs);
     151    return *this;
     152  }
     153};
     154
    107155
    108156/** @class CountedRefData
     
    116164  typedef RefCounter base;
    117165
    118   /// Forbit copy construction and normal assignment
    119   CountedRefData(const self&);
    120   self& operator=(const self&);
    121 
    122166public:
    123167  /// 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
     168  explicit CountedRefData(leftv data, idhdl* ctx = &IDROOT):
     169    base(), m_data(data), m_context(ctx) { context(); }
     170
     171  /// Construct deep copy
     172  CountedRefData(const self& rhs):
     173    base(), m_data(rhs.m_data), m_context(rhs.m_context) { }
     174 
     175  /// Destruct
    135176  ~CountedRefData()  { }
    136177
    137   BOOLEAN get(leftv result) {
    138     if (m_ring && (m_ring != currRing)) {
    139       Werror("Can only use references from current ring.");
    140       return TRUE;
    141     }
    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);
    152   }
     178  /// Replace data
     179  self& operator=(const self& rhs) {
     180    m_data = rhs.m_data;
     181    m_context = rhs.m_context;
     182    return *this;
     183  }
     184 
     185  /// Replace with other Singular data
     186  void set(leftv rhs, idhdl* ctx = &IDROOT) {
     187    m_data = rhs;
     188    m_context = ctx;
     189    context();
     190  }
     191
     192  /// Write (shallow) copy to given handle
     193  BOOLEAN get(leftv res) {
     194    reclaim();
     195    BOOLEAN b = broken() || m_data.get(res);
     196    release();
     197    return b;
     198  }
     199
     200  /// Extract (shallow) copy of stored data
     201  LeftvShallow operator*() { return (broken()? LeftvShallow(): m_data); }
    153202
    154203private:
     204  /// Check whether identifier became invalid
     205  /// @note Sergio Leone memorial function
     206  BOOLEAN broken() {
     207    if( (m_context == getmyroot()) || (m_context == &currRing->idroot))
     208      return FALSE;                  // the good,
     209
     210    if (m_data->RingDependend())     // the bad,
     211      return complain("Referenced identifier not available in current ring");
     212
     213    return (brokenid(m_context) &&   // and the ugly (case)
     214            ((m_context == &basePack->idroot) || brokenid())) &&
     215      complain("Referenced identifier not found in current context");
     216  }
     217
     218  /// Determine corresponding context
     219  /// @note for ring-dependent object we always store @c currRing's root as marker
     220  void context() { if (m_data->RingDependend()) m_context = &currRing->idroot; }
     221
     222  ///
     223  BOOLEAN complain(const char* text) {
     224    Werror(text);
     225    return TRUE;
     226  }
     227  BOOLEAN brokenid(idhdl* root = &basePack->idroot) {
     228    idhdl handle = (idhdl) m_data->data;
     229    for(idhdl current = *root; current != NULL; current = IDNEXT(current))
     230      if (current == handle) return FALSE;
     231    return TRUE;
     232  }
     233
    155234
    156235  /// Singular object
    157   LeftvShallow m_data;
    158 
    159   /// Store ring for ring-dependent objects
    160   ring m_ring;
     236  LeftvDeep m_data;
     237
     238  /// Store namespace for ring-dependent objects
     239  idhdl* m_context;
    161240};
    162241
     
    179258
    180259  /// Check whether argument is already a reference type
    181   static BOOLEAN is_ref(int typ) {
     260  static BOOLEAN is_ref(leftv arg) {
     261    int typ = arg->Typ();
    182262    return ((typ > MAX_TOK) &&
    183263           (getBlackboxStuff(typ)->blackbox_Init == countedref_Init));
    184264  }
    185265
    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();
     266  /// Construct new reference from Singular data 
     267  CountedRef(leftv arg):  m_data(new data_type(arg)) { m_data->reclaim(); }
     268
     269protected:
     270  /// Recover previously constructed reference
     271  CountedRef(data_type* arg):  m_data(arg) { assume(arg); m_data->reclaim(); }
     272
     273public:
     274  /// Construct copy
     275  CountedRef(const self& rhs): m_data(rhs.m_data) { m_data->reclaim(); }
     276
     277  /// Replace reference
     278  self& operator=(const self& rhs) {
     279    destruct();
     280    m_data = rhs.m_data;
     281    m_data->reclaim();
     282    return *this;
     283  }
     284
     285  /// Replace data that reference is pointing to
     286  self& operator=(leftv rhs) {
     287    m_data->set(rhs);
     288    return *this;
     289  }
     290
     291  /// Extract (shallow) copy of stored data
     292  LeftvShallow operator*() { return m_data->operator*(); }
     293
     294  /// Construct reference data object from
     295  BOOLEAN outcast(leftv result) {
     296    m_data->reclaim();
    191297    if (result->rtyp == IDHDL)
    192       IDDATA((idhdl)result->data) = (char *)data;
     298      IDDATA((idhdl)result->data) = (char *)m_data;
    193299    else
    194       result->data = (void *)data;
    195     return (data == NULL? TRUE: FALSE);
    196   }
     300      result->data = (void *)m_data;
     301    return FALSE;
     302  }
     303  data_type* outcast() {
     304    m_data->reclaim();
     305    return m_data;
     306  }
     307  /// Kills a link to the referenced object
     308  void destruct() { if(!m_data->release()) delete m_data; }
    197309
    198310  /// Kills the link to the referenced object
    199   static void destruct(data_type* data) {
    200     if(data && !data->release()) {
    201       delete data;
    202     }
    203   }
     311  ~CountedRef() { destruct(); }
     312
     313  BOOLEAN dereference(leftv arg) {
     314    assume(is_ref(arg));
     315    return m_data->get(arg) || ((arg->next != NULL) && resolve(arg->next));
     316  }
     317
    204318
    205319  /// Get the actual object
    206320  /// @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);
     321
     322  static self cast(void* data) {
     323    assume(data != NULL);
     324    return self(static_cast<data_type*>(data));
     325  }
     326
     327  static self cast(leftv arg) {
     328    assume((arg != NULL) && is_ref(arg));
     329    return self::cast(arg->Data());
    215330  }
    216331
     
    219334  static BOOLEAN resolve(leftv arg) {
    220335    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   }
     336    while (is_ref(arg)) { if(CountedRef::cast(arg).dereference(arg)) return TRUE; };
     337    return (arg->next != NULL) && resolve(arg->next);
     338  }
     339
     340  //private:
     341protected:
     342  /// Store pointer to actual data
     343  data_type* m_data;
    233344};
    234345
     
    236347void countedref_Print(blackbox *b, void* ptr)
    237348{
    238   if (ptr != NULL) static_cast<CountedRefData*>(ptr)->get()->Print();
     349  if (ptr == NULL)  return;
     350  (*CountedRef::cast(ptr))->Print();
    239351}
    240352
     
    242354char* countedref_String(blackbox *b, void* ptr)
    243355{
    244   if (ptr != NULL) return static_cast<CountedRefData*>(ptr)->get()->String();
     356  if (ptr == NULL) return NULL;
     357  return (*CountedRef::cast(ptr))->String();
    245358}
    246359
     
    248361void* countedref_Copy(blackbox*b, void* ptr)
    249362{
    250   if (ptr) static_cast<CountedRefData*>(ptr)->reclaim();
    251   return ptr;
     363  if (ptr) return CountedRef::cast(ptr).outcast();
     364  return NULL;
    252365}
    253366
     
    256369{
    257370  // Case: replace assignment behind reference
    258   if (result->Data() != NULL)
    259     return CountedRef::dereference(result) || CountedRef::resolve(arg) ||
     371  if (result->Data() != NULL) {
     372    return CountedRef::cast(result).dereference(result) ||
     373      CountedRef::resolve(arg) ||
    260374      iiAssign(result, arg);
     375  }
    261376 
    262377  // Case: new reference
    263378  if(arg->rtyp == IDHDL)
    264     return CountedRef::construct(result, arg);
    265  
     379    return (result->Typ() == arg->Typ()?
     380            CountedRef::cast(arg):
     381            CountedRef(arg)).outcast(result);
     382
    266383  Werror("Can only take reference from identifier");
    267384  return FALSE;
     
    274391    return blackboxDefaultOp1(op, res, head);
    275392
    276   return CountedRef::dereference(head) ||
     393  return CountedRef::cast(head).dereference(head) ||
    277394    iiExprArith1(res, head, (op == DEF_CMD? head->Typ(): op));
    278395}
     
    281398BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg)
    282399{
    283   return CountedRef::dereference(head) || CountedRef::resolve(arg) ||
     400
     401  return CountedRef::cast(head).dereference(head) || CountedRef::resolve(arg) ||
    284402    iiExprArith2(res, head, op, arg);
    285403}
     
    288406BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2)
    289407{
    290   return CountedRef::dereference(head) ||
     408  return  CountedRef::cast(head).dereference(head) ||
    291409    CountedRef::resolve(arg1) || CountedRef::resolve(arg2) ||
    292410    iiExprArith3(res, op, head, arg1, arg2);
     
    297415BOOLEAN countedref_OpM(int op, leftv res, leftv args)
    298416{
    299   return CountedRef::dereference(args) || iiExprArithM(res, args, op);
     417  return CountedRef::cast(args).dereference(args) || iiExprArithM(res, args, op);
    300418}
    301419
     
    303421void countedref_destroy(blackbox *b, void* ptr)
    304422{
    305   CountedRef::destruct(static_cast<CountedRefData*>(ptr));
    306 }
     423  if (ptr) CountedRef::cast(ptr).destruct();
     424}
     425
     426
     427class CountedRefShared:
     428  public CountedRef {
     429  typedef CountedRefShared self;
     430  typedef CountedRef base;
     431public:
     432  /// Construct new reference from Singular data 
     433  CountedRefShared(leftv arg):  base(new data_type(wrap(arg), getmyroot())) { }
     434
     435private:
     436  /// Recover previously constructed shared data
     437  CountedRefShared(data_type* arg):  base(arg) { }
     438  CountedRefShared(const base& rhs):  base(rhs) { }
     439public:
     440  /// Construct copy
     441  CountedRefShared(const self& rhs): base(rhs) { }
     442
     443  ~CountedRefShared() {  kill(); }
     444
     445  self& operator=(const self& rhs) {
     446    kill();
     447    base::operator=(rhs);
     448    return *this;
     449  }
     450
     451  /// Replace data that reference is pointing to
     452  self& operator=(leftv rhs) {
     453    m_data->set(wrap(rhs), getmyroot());
     454    return *this;
     455  }
     456  void destruct() {
     457    kill();
     458    base::destruct();
     459  }
     460
     461  static self cast(leftv arg) { return base::cast(arg); }
     462  static self cast(void* arg) { return base::cast(arg); }
     463private:
     464
     465  static leftv wrap(leftv arg) {
     466      char* name = (char*)omAlloc0(512);
     467      static unsigned int counter = 0;
     468      idhdl* myroot=getmyroot();
     469      sprintf(name, " :%u:%p:_shared_: ", ++counter, arg->Data());
     470      assume((*myroot)->get(name, 0) == NULL);
     471      idhdl handle = (*myroot)->set(name, 0, arg->Typ(), FALSE);
     472      ++(*myroot)->ref;
     473
     474      IDDATA(handle) = (char*) arg->CopyD();
     475      arg->CleanUp();
     476      arg->data = handle;
     477      arg->rtyp = IDHDL;
     478      arg->name = name;
     479
     480    return arg;
     481  }
     482
     483 void kill() {
     484   if (m_data->count() > 1) return;
     485
     486   LeftvShallow data = base::operator*();
     487   idhdl* myroot = getmyroot();
     488   killhdl2((idhdl)(data->data), myroot, currRing);
     489   data->data = NULL;
     490   data->rtyp = NONE;
     491   
     492   if(--((*myroot)->ref)) {
     493     killhdl2(*myroot, &IDROOT, currRing);
     494     (*myroot) = NULL;
     495   }
     496 }
     497};
    307498
    308499
     
    310501BOOLEAN countedref_AssignShared(leftv result, leftv arg)
    311502{
    312   // Case: replace assignment behind reference
    313   if (result->Data() != NULL)
    314     return CountedRef::dereference(result) || CountedRef::resolve(arg) ||
    315       iiAssign(result, arg);
     503  /// Case: replace assignment behind reference
     504  if ((result->Data()) != NULL) {
     505    if (CountedRefShared::resolve(arg)) return TRUE;
     506    CountedRefShared::cast(result) = arg;
     507    return FALSE;
     508  }
    316509 
    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);
     510  /// Case: new shared data
     511  if (result->Typ() == arg->Typ())
     512    return CountedRefShared::cast(arg).outcast(result);
     513
     514  return CountedRefShared(arg).outcast(result);
    339515}
    340516
     
    342518void countedref_destroyShared(blackbox *b, void* ptr)
    343519{
    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 
     520  if (ptr) CountedRefShared::cast(ptr).destruct();
    353521}
    354522
     
    369537  setBlackboxStuff(bbx, "reference");
    370538
     539  /// The @c shared type is "inherited" from @c reference.
     540  /// It just uses another constructor (to make its own copy of the).
    371541  blackbox *bbxshared =
    372542    (blackbox*)memcpy(omAlloc(sizeof(blackbox)), bbx, sizeof(blackbox));
    373543  bbxshared->blackbox_Assign  = countedref_AssignShared;
    374   bbxshared->blackbox_destroy = countedref_destroyShared;
     544  bbxshared->blackbox_destroy  = countedref_destroyShared;
     545
    375546  setBlackboxStuff(bbxshared, "shared");
    376547}
Note: See TracChangeset for help on using the changeset viewer.