Changeset 75c668 in git


Ignore:
Timestamp:
Aug 14, 2012, 3:35:17 PM (10 years ago)
Author:
Alexander Dreyer <alexander.dreyer@…>
Branches:
(u'jengelh-datetime', 'ceac47cbc86fe4a15902392bdbb9bd2ae0ea02c6')(u'spielwiese', '96ce329119711a2b80858c8365abd29f8460bbfa')
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
Message:
Introducing blackbox type "shared"

fix: newstruc's subexpressions working
fix: support subexpr of subexpr
chg: simplified reference dereferencing
chg: simplified shallow copies of sleftv
new: blackbox type
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Singular/countedref.cc

    r971984c r75c668  
    3333
    3434
    35 class CountedRef {
    36   typedef CountedRef self;
     35class CountedRefEnv {
     36  typedef CountedRefEnv self;
     37
     38
     39
     40};
     41
     42class RefCounter {
     43  typedef RefCounter self;
     44
     45  /// Name numerical type for enumbering
     46  typedef unsigned long count_type;
    3747
    3848public:
    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) {}
    8754
    8855  /// 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); }
    11557
    11658  /// @name Reference counter management
     
    12163  //@}
    12264
    123   leftv get () {
    124     leftv result = (leftv)omAlloc0(sizeof(sleftv));
    125     get(*result);
    126     return result;
    127   }
    128 
    129   void get(sleftv& result) {
     65private:
     66  /// Number of references
     67  count_type m_count;
     68};
     69
     70class LeftvShallow {
     71  typedef LeftvShallow self;
     72
     73public:
     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
     92private:
     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 **/
     113class 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
     122public:
     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) {
    130138    if (m_ring && (m_ring != currRing)) {
    131139      Werror("Can only use references from current ring.");
    132       return;
     140      return TRUE;
    133141    }
    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);
    137152  }
    138153
    139154private:
    140   /// Reference counter
    141   count_type m_count;
    142155
    143156  /// Singular object
    144   sleftv m_data;
     157  LeftvShallow m_data;
    145158
    146159  /// Store ring for ring-dependent objects
     
    148161};
    149162
    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.
     165void* countedref_Init(blackbox*)
     166{
     167  return NULL;
     168}
     169
     170class CountedRef {
     171  typedef CountedRef self;
     172
     173public:
     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;
    183202    }
    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
     225private:
     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};
    224234
    225235/// blackbox support - convert to string representation
    226236void countedref_Print(blackbox *b, void* ptr)
    227237{
    228   if (ptr != NULL) CountedRefCast(ptr)->Print();
     238  if (ptr != NULL) static_cast<CountedRefData*>(ptr)->get()->Print();
    229239}
    230240
     
    232242char* countedref_String(blackbox *b, void* ptr)
    233243{
    234   if (ptr != NULL) return CountedRefCast(ptr)->String();
     244  if (ptr != NULL) return static_cast<CountedRefData*>(ptr)->get()->String();
    235245}
    236246
     
    246256{
    247257  // 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);
    250261 
    251262  // Case: new reference
    252263  if(arg->rtyp == IDHDL)
    253     return CountedRefData::construct(result, arg);
     264    return CountedRef::construct(result, arg);
    254265 
    255266  Werror("Can only take reference from identifier");
    256   return CountedRefData::set_to(result, NULL, NONE);
     267  return FALSE;
    257268}
    258269                                                                     
    259 
    260270/// blackbox support - unary operations
    261271BOOLEAN countedref_Op1(int op, leftv res, leftv head)
    262272{
    263273  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));
    272278}
    273279
     
    275281BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg)
    276282{
    277   return iiExprArith2(res, CountedRefCast(head), op, CountedRefAccess(arg));
     283  return CountedRef::dereference(head) || CountedRef::resolve(arg) ||
     284    iiExprArith2(res, head, op, arg);
    278285}
    279286
     
    281288BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2)
    282289{
    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);
    285293}
    286294
     
    289297BOOLEAN countedref_OpM(int op, leftv res, leftv args)
    290298{
    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);
    304300}
    305301
     
    307303void countedref_destroy(blackbox *b, void* ptr)
    308304{
    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
     310BOOLEAN 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
     342void 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
    312353}
    313354
     
    326367  bbx->blackbox_OpM     = countedref_OpM;
    327368  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");
    329376}
    330377
Note: See TracChangeset for help on using the changeset viewer.