source: git/Singular/countedref.cc @ 2fbb4e0

spielwiese
Last change on this file since 2fbb4e0 was 2fbb4e0, checked in by Alexander Dreyer <alexander.dreyer@…>, 12 years ago
fix: const qualifiers and simplified ref counting
  • Property mode set to 100644
File size: 22.7 KB
Line 
1/// -*- c++ -*-
2//*****************************************************************************
3/** @file countedref.cc
4 *
5 * @author Alexander Dreyer
6 * @date 2010-12-15
7 *
8 * This file defines the @c blackbox operations for the countedref type.
9 *
10 * @par Copyright:
11 *   (c) 2010 by The Singular Team, see LICENSE file
12**/
13//*****************************************************************************
14
15
16
17
18
19#include <Singular/mod2.h>
20
21#include <Singular/ipid.h>
22#include <Singular/blackbox.h>
23#include <Singular/newstruct.h>
24
25#include <omalloc/omalloc.h>
26#include <kernel/febase.h>
27#include <kernel/longrat.h>
28#include <Singular/subexpr.h>
29#include <Singular/ipshell.h>
30
31#include "lists.h"
32#include "attrib.h"
33
34/** @class CountedRefPtr
35 * This class implements a smart pointer which handles pointer-style access
36 * to a reference-counted structure and destructing the latter after use.
37 *
38 * The template arguments, include the pointer type @c PtrType, and two
39 * integral (bool) properties: use @c isWeak to disallow destruction
40 * and @c NeverNull to assume, that @c PtrType cannot be @c NULL.
41 * Finally, @c CountType allows you to select a typ to represent the internal reference count.
42 *
43 * @note The class of @c PtrType must have an accessible integral attribute @c ref.
44 * For convenience use @c RefCounter as public base.
45 * In addition you must overload @c void CountedRefPtr_kill(PtrType) accordingly.
46 **/
47template <class PtrType, bool isWeak = false, bool NeverNull = false, class CountType = short>
48class CountedRefPtr {
49  typedef CountedRefPtr self;
50
51public:
52  //{ @name Name template arguments
53  typedef PtrType ptr_type;
54  typedef CountType count_type;
55  enum { is_weak = isWeak, never_null = NeverNull };
56  //}
57
58  /// Convert from pointer
59  CountedRefPtr(ptr_type ptr): m_ptr(ptr) { reclaim(); }
60
61  /// Convert from compatible smart pointer
62  template <bool Never>
63  CountedRefPtr(const CountedRefPtr<ptr_type, !is_weak, Never, count_type>& rhs):
64    m_ptr(rhs.m_ptr) { reclaim(); }
65
66  /// Construct refernce copy
67  CountedRefPtr(const self& rhs):
68    m_ptr(rhs.m_ptr) { reclaim(); }
69
70  /// Unlink one reference
71  ~CountedRefPtr() { release(); }
72
73  //{ @name Replace data behind reference
74  self& operator=(const self& rhs) { return operator=(rhs.m_ptr); }
75  self& operator=(ptr_type ptr) {
76    release();
77    m_ptr = ptr;
78    reclaim();
79    return *this;
80  }
81  //}
82
83  /// Checking equality
84  bool operator==(const self& rhs) const { return m_ptr == rhs.m_ptr; }
85
86  //{ @name Pointer-style interface
87  bool operator==(ptr_type ptr) const { return m_ptr == ptr; }
88  operator bool() const { return NeverNull || m_ptr; }
89  operator const ptr_type() const { return m_ptr; }
90  operator ptr_type() { return m_ptr; }
91  const ptr_type operator->() const { return *this; }
92  ptr_type operator->() { return *this; }
93  //}
94
95  //{ @name Reference count interface
96  count_type count() const { return (*this? m_ptr->ref: 1); }
97  void reclaim() { if (*this) ++m_ptr->ref; }
98  void release() { 
99    if (*this && (--m_ptr->ref <= 0) && !is_weak)
100      CountedRefPtr_kill(m_ptr); 
101  }
102  //}
103
104private:
105  /// Store actual pointer
106  ptr_type m_ptr;
107};
108
109
110/** @class RefCounter
111 * This class implements implements a refernce counter which we can use
112 * as a public base of objects managed by @CountedRefPtr.
113 **/
114class RefCounter {
115
116public:
117  /// Name numerical type for enumbering
118  typedef short count_type;
119
120  /// Allow our smart pointer to access internals
121  template <class, bool, bool, class> friend class CountedRefPtr;
122
123  /// Any Constructor resets the counter
124  RefCounter(...): ref(0) {}
125
126  /// Destructor
127  ~RefCounter() { assume(ref == 0); }
128
129private:
130  /// Number of references
131  count_type ref;  // naming consistent with other classes
132};
133
134class CountedRefEnv {
135  typedef CountedRefEnv self;
136
137public:
138  static idhdl idify(leftv head, idhdl* root) {
139    static unsigned int counter = 0;
140    char* name = (char*) omAlloc0(512);
141    sprintf(name, " :%u:%p:_shared_: ", ++counter, head->data);
142    if ((*root) == NULL )
143      enterid(name, 0, head->rtyp, root, TRUE, FALSE);
144    else
145      *root = (*root)->set(name, 0, head->rtyp, TRUE);
146
147    IDDATA(*root) = (char*) head->data;
148    return *root;
149  }
150
151  static void clearid(idhdl handle, idhdl* root) {
152    IDDATA(handle)=NULL;
153    IDTYP(handle)=NONE;
154    killhdl2(handle, root, NULL);
155  }
156  static int& ref_id() {
157    static int g_ref_id = 0;
158    return g_ref_id;
159  }
160
161  static int& sh_id() {
162    static int g_sh_id = 0;
163    return g_sh_id;
164  }
165  static int& idx_id() {
166    static int g_sh_id = 0;
167    return g_sh_id;
168  }
169
170};
171
172/// Overloading ring destruction
173inline void CountedRefPtr_kill(ring r) { rKill(r); }
174
175
176class LeftvShallow {
177  typedef LeftvShallow self;
178 
179public:
180  LeftvShallow(): m_data(allocate()) { }
181  LeftvShallow(leftv data): 
182    m_data(allocate()) { init(data); }
183
184  LeftvShallow(const self& rhs):
185    m_data(allocate()) {
186    copy(m_data, rhs.m_data);
187  }
188
189  ~LeftvShallow() { 
190    kill(m_data->e);
191    omFree(m_data);
192  }
193  self& operator=(leftv rhs) {
194    kill(m_data->e);
195    return init(rhs);
196  }
197
198  self& operator=(const self& rhs) { return (*this) = rhs.m_data; }
199
200
201
202  BOOLEAN get(leftv result) {
203    leftv next = result->next;
204    result->next = NULL;
205    result->CleanUp();
206
207    copy(result, m_data);
208    result->next = next;
209    return FALSE;
210  }
211
212  /// Access to object
213  const leftv operator->() const { return m_data;  }
214  leftv operator->() { return m_data;  }
215
216protected:
217  static leftv allocate() { return (leftv)omAlloc0(sizeof(sleftv)); }
218
219  self& init(leftv data) {
220    memcpy(m_data, data, sizeof(sleftv));
221    data->e = NULL;
222    m_data->next = NULL;
223    return *this;
224  }
225
226  static void copy(leftv result, leftv data)  {
227    memcpy(result, data, sizeof(sleftv));
228    copy(result->e, data->e);
229  }
230
231 static void copy(Subexpr& current, Subexpr rhs)  {
232    if (rhs == NULL) return;
233    current = (Subexpr)memcpy(omAlloc0Bin(sSubexpr_bin), rhs, sizeof(*rhs));
234    copy(current->next, rhs->next);
235  }
236
237  static void kill(Subexpr current) {
238    if(current == NULL) return;
239    kill(current->next);
240    omFree(current);
241  }
242
243protected:
244  leftv m_data;
245};
246
247
248class LeftvDeep:
249  public LeftvShallow {
250  typedef LeftvDeep self;
251  typedef LeftvShallow base;
252
253public:
254  LeftvDeep(): base() {}
255  LeftvDeep(leftv data): base(data) {
256    if(m_data->rtyp != IDHDL) {
257      m_data->data = data->CopyD();
258    }
259  }
260
261  LeftvDeep(leftv data,int,int): base() {  m_data->Copy(data);  }
262
263  LeftvDeep(const self& rhs): base(rhs) {
264    if(m_data->rtyp != IDHDL)
265      m_data->Copy(rhs.m_data);
266  }
267
268  ~LeftvDeep() { m_data->CleanUp(); }
269
270  self& operator=(const self& rhs) { return operator=(rhs.m_data); }
271  self& operator=(leftv rhs) {
272    m_data->e = rhs->e;
273    rhs->e=NULL;
274    if(m_data->rtyp == IDHDL) {
275      IDTYP((idhdl)m_data->data) =  rhs->Typ();
276      IDDATA((idhdl)m_data->data) = (char*) rhs->CopyD();
277    }
278    else {
279      m_data->CleanUp();
280      m_data->rtyp = rhs->Typ();
281      m_data->data =  rhs->CopyD();
282    }
283
284    return *this;
285  }
286
287   leftv access() { return m_data; }
288};
289
290/** @class CountedRefData
291 * This class stores a reference counter as well as a Singular interpreter object.
292 *
293 * It also stores the Singular token number, once per type.
294 **/
295class CountedRefData:
296  public RefCounter {
297  typedef CountedRefData self;
298  typedef RefCounter base;
299
300public:
301  /// Construct reference for Singular object
302  explicit CountedRefData(leftv data):
303    base(), m_data(data), m_ring(parent(data)) { }
304
305  CountedRefData(leftv data, BOOLEAN global, int):
306    base(), m_data(data, global,0), m_ring(parent(data)) { }
307
308  /// Construct deep copy
309  CountedRefData(const self& rhs):
310    base(), m_data(rhs.m_data), m_ring(rhs.m_ring)  { }
311 
312  /// Destruct
313  ~CountedRefData()  { }
314
315  /// Replace data
316  self& operator=(const self& rhs) {
317    m_data = rhs.m_data;
318    m_ring = rhs.m_ring;
319    return *this;
320  }
321
322  /// Replace with other Singular data
323  void set(leftv rhs) {
324    if (m_data->rtyp==IDHDL)
325      m_data = rhs;
326   else
327     m_data->Copy(rhs);
328
329    m_ring = parent(rhs);
330  }
331
332  /// Write (shallow) copy to given handle
333  BOOLEAN get(leftv res) { return broken() || m_data.get(res);  }
334
335  /// Extract (shallow) copy of stored data
336  LeftvShallow operator*() const { return (broken()? LeftvShallow(): LeftvShallow(m_data)); }
337
338
339  BOOLEAN rering() {
340    if (m_ring ^ m_data->RingDependend()) m_ring = (m_ring? NULL: currRing);
341    return FALSE;
342  }
343
344  /// Get the current context
345  idhdl* root() { return  (m_ring? &m_ring->idroot: &IDROOT); }
346
347  /// Check whether identifier became invalid
348  BOOLEAN broken() const {
349    if (m_ring) {
350      if (m_ring != currRing) 
351        return complain("Referenced identifier not from current ring");   
352
353      return (m_data->rtyp == IDHDL)  && brokenid(currRing->idroot) &&
354        complain("Referenced identifier not available in ring anymore"); 
355    }
356
357   if (m_data->rtyp != IDHDL) return FALSE;
358   return brokenid(IDROOT) &&
359     ((currPack == basePack) || brokenid(basePack->idroot)) &&
360     complain("Referenced identifier not available in current context");
361  }
362
363  BOOLEAN assign(leftv result, leftv arg) {
364    return get(result) || iiAssign(result, arg) || rering();
365  }
366
367  /// @note Enables write-access via identifier
368  idhdl idify() {  return CountedRefEnv::idify(m_data.access(), root());  }
369
370  /// @note Only call, if @c idify had been called before!
371  void clearid() {  CountedRefEnv::clearid((idhdl)m_data.access()->data, root());  }
372
373  BOOLEAN retrieve(leftv res) {
374    if (res->data == m_data.access()->data)  {
375      memcpy(m_data.access(), res, sizeof(sleftv));
376      res->Init();
377      return TRUE;
378    }
379    return FALSE;
380  }
381
382  CountedRefPtr<ring, true> Ring() { return m_ring; }
383
384private:
385  /// Raise error message and return @c TRUE
386  BOOLEAN complain(const char* text) const  {
387    Werror(text);
388    return TRUE;
389  }
390
391  /// Check a given context for our identifier
392  BOOLEAN brokenid(idhdl context) const {
393    return (context == NULL) || 
394      ((context != (idhdl) m_data->data) && brokenid(IDNEXT(context)));
395  }
396
397  /// Store ring for ring-dependent objects
398  static ring parent(leftv rhs) { 
399    return (rhs->RingDependend()? currRing: NULL); 
400  }
401protected:
402  /// Singular object
403  LeftvDeep m_data;
404
405  /// Store namespace for ring-dependent objects
406  CountedRefPtr<ring, true> m_ring;
407};
408
409/// blackbox support - initialization
410/// @note deals as marker for compatible references, too.
411void* countedref_Init(blackbox*)
412{
413  return NULL;
414}
415
416
417inline void CountedRefPtr_kill(CountedRefData* data) { delete data; }
418
419class CountedRef {
420  typedef CountedRef self;
421
422public:
423  /// name type for identifiers
424  typedef int id_type;
425
426  /// Name type for handling reference data
427  typedef CountedRefData data_type;
428
429  /// Check whether argument is already a reference type
430  static BOOLEAN is_ref(leftv arg) {
431    int typ = arg->Typ();
432    return ((typ > MAX_TOK) &&
433           (getBlackboxStuff(typ)->blackbox_Init == countedref_Init));
434  }
435
436  /// Construct new reference from Singular data 
437  CountedRef(leftv arg):  m_data(new data_type(arg)) { }
438
439protected:
440  /// Recover previously constructed reference
441  CountedRef(data_type* arg):  m_data(arg) { assume(arg); }
442
443public:
444  /// Construct copy
445  CountedRef(const self& rhs): m_data(rhs.m_data) { }
446
447  /// Replace reference
448  self& operator=(const self& rhs) {
449    m_data = rhs.m_data;
450    return *this;
451  }
452
453  /// Replace data that reference is pointing to
454  self& operator=(leftv rhs) {
455    m_data->set(rhs);
456    return *this;
457  }
458
459  BOOLEAN assign(leftv result, leftv arg) { 
460    return m_data->assign(result,arg);
461  }
462
463  /// Extract (shallow) copy of stored data
464  LeftvShallow operator*() { return m_data->operator*(); }
465
466  /// Construct reference data object from
467  BOOLEAN outcast(leftv result) {
468    if (result->rtyp == IDHDL)
469      IDDATA((idhdl)result->data) = (char *)outcast();
470    else
471      result->data = (void *)outcast();
472    return FALSE;
473  }
474  data_type* outcast() { 
475    m_data.reclaim();
476    return m_data;
477  }
478
479  /// Kills a link to the referenced object
480  void destruct() { m_data.release(); }
481
482  /// Kills the link to the referenced object
483  ~CountedRef() { }
484
485  /// Replaces argument by a shallow copy of the references data
486  BOOLEAN dereference(leftv arg) {
487    //    assume(is_ref(arg));
488    m_data.reclaim();
489    BOOLEAN b= m_data->get(arg) || ((arg->next != NULL) && resolve(arg->next));
490    m_data.release();
491    return b;
492  }
493
494  BOOLEAN broken() {return m_data->broken(); }
495
496  /// Get number of references pointing here, too
497  BOOLEAN count(leftv res) { return construct(res, m_data.count() - 1); }
498
499  // Get internal indentifier
500  BOOLEAN hash(leftv res) { return construct(res, (long)(data_type*)m_data); }
501
502  /// Check for likewise identifiers
503  BOOLEAN likewise(leftv res, leftv arg) {
504    return resolve(arg) || construct(res, operator*()->data == arg->data); 
505  }
506
507  /// Check for identical reference objects
508  BOOLEAN same(leftv res, leftv arg) { 
509    return construct(res, m_data == arg->Data());
510  }
511
512  /// Get type of references data
513  BOOLEAN type(leftv res) { 
514    return construct(res, Tok2Cmdname(operator*()->Typ()));
515  };
516
517  /// Get (possibly) internal identifier name
518  BOOLEAN name(leftv res) { return construct(res, operator*()->Name()); }
519
520  /// Recover the actual object from raw Singular data
521  static self cast(void* data) {
522    assume(data != NULL);
523    return self(static_cast<data_type*>(data));
524  }
525
526  /// Recover the actual object from Singular interpreter object
527  static self cast(leftv arg) {
528    assume((arg != NULL) && is_ref(arg));
529    return self::cast(arg->Data());
530  }
531
532  /// If necessary dereference.
533  static BOOLEAN resolve(leftv arg) {
534    assume(arg != NULL);
535    while (is_ref(arg)) { if(CountedRef::cast(arg).dereference(arg)) return TRUE; };
536    return (arg->next != NULL) && resolve(arg->next);
537  }
538
539protected:
540  /// Construct integer value
541  static BOOLEAN construct(leftv res, long data) {
542    res->data = (void*) data;
543    res->rtyp = INT_CMD;
544    return FALSE;
545  }
546
547  /// Construct string
548  static BOOLEAN construct(leftv res, const char* data) {
549    res->data = (void*)omStrDup(data);
550    res->rtyp = STRING_CMD;
551    return FALSE;
552  }
553
554  /// Store pointer to actual data
555  CountedRefPtr<data_type*> m_data;
556};
557
558/// blackbox support - convert to string representation
559void countedref_Print(blackbox *b, void* ptr)
560{
561  if (ptr) (*CountedRef::cast(ptr))->Print();
562  else PrintS("<unassigned reference or shared memory>");
563}
564
565/// blackbox support - convert to string representation
566char* countedref_String(blackbox *b, void* ptr)
567{
568  if (ptr == NULL) return omStrDup(sNoName);
569  return (*CountedRef::cast(ptr))->String();
570}
571
572/// blackbox support - copy element
573void* countedref_Copy(blackbox*b, void* ptr)
574{ 
575  if (ptr) return CountedRef::cast(ptr).outcast();
576  return NULL;
577}
578
579/// blackbox support - assign element
580BOOLEAN countedref_Assign(leftv result, leftv arg)
581{
582  // Case: replace assignment behind reference
583  if (result->Data() != NULL) {
584    return CountedRef::resolve(arg) || 
585      CountedRef::cast(result).assign(result, arg);     
586  }
587 
588  // Case: copy reference
589  if (result->Typ() == arg->Typ())
590    return CountedRef::cast(arg).outcast(result);
591
592  // Case: new reference
593  if ((arg->rtyp == IDHDL) || CountedRef::is_ref(arg))
594    return CountedRef(arg).outcast(result);
595
596  Werror("Can only take reference from identifier");
597  return TRUE;
598}
599
600BOOLEAN countedref_CheckInit(leftv res, leftv arg)
601{
602  if (arg->Data() != NULL) return FALSE;
603  res->rtyp = NONE;
604  Werror("Noninitialized access");
605  return TRUE;
606}
607                                                                 
608/// blackbox support - unary operations
609BOOLEAN countedref_Op1(int op, leftv res, leftv head)
610{
611  if(op == TYPEOF_CMD)
612    return blackboxDefaultOp1(op, res, head);
613
614  if (countedref_CheckInit(res, head)) return TRUE;
615
616  if(op == head->Typ()) {
617    res->rtyp = op;
618    return iiAssign(res, head);
619  }
620
621  if(op == DEF_CMD) {
622    res->rtyp = DEF_CMD;
623    return CountedRef::cast(head).dereference(head) || iiAssign(res, head);
624  }
625
626  return CountedRef::cast(head).dereference(head) || iiExprArith1(res, head, op);
627}
628
629/// blackbox support - binary operations
630BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg)
631{
632   return countedref_CheckInit(res, head) ||
633    CountedRef::cast(head).dereference(head) ||
634    CountedRef::resolve(arg) ||
635    iiExprArith2(res, head, op, arg);
636}
637
638class CountedRefDataIndexed:
639  public CountedRefData {
640  typedef CountedRefData base;
641  typedef CountedRefDataIndexed self;
642
643public:
644  CountedRefDataIndexed(idhdl handle, CountedRefPtr<base*> back):
645    base(init(handle)), m_back(back) { 
646    m_ring = back->Ring(); 
647  } 
648
649  CountedRefDataIndexed(const self& rhs): base(rhs), m_back(rhs.m_back) { } 
650
651  ~CountedRefDataIndexed() { clearid();}
652
653  BOOLEAN assign(leftv result, leftv arg) {
654    return base::assign(result, arg) || m_back->rering();
655  }
656
657private:
658  static leftv init(idhdl handle) {
659    assume(handle);
660    leftv res = (leftv)omAlloc0(sizeof(*res));
661    res->data =(void*) handle;
662    res->rtyp = IDHDL;
663    return res;
664  }
665
666  CountedRefPtr<CountedRefData*> m_back;
667};
668inline void CountedRefPtr_kill(CountedRefDataIndexed* data) { delete data; }
669
670
671
672/// blackbox support - ternary operations
673BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2)
674{
675  return countedref_CheckInit(res, head) ||
676    CountedRef::cast(head).dereference(head) || 
677    CountedRef::resolve(arg1) || CountedRef::resolve(arg2) ||
678    iiExprArith3(res, op, head, arg1, arg2);
679}
680
681
682
683/// blackbox support - destruction
684void countedref_destroy(blackbox *b, void* ptr)
685{
686  if (ptr) CountedRef::cast(ptr).destruct();
687}
688
689
690/// blackbox support - assign element
691BOOLEAN countedref_AssignIndexed(leftv result, leftv arg)
692{
693  // Case: replace assignment behind reference
694  if (result->Data() != NULL) {
695    CountedRefPtr<CountedRefDataIndexed*> indexed =(CountedRefDataIndexed*)(result->Data());
696    return CountedRef::resolve(arg) || indexed->assign(result, arg);
697  }
698 
699  // Case: copy reference
700  if (result->Typ() == arg->Typ())
701    return CountedRef::cast(arg).outcast(result);
702
703  Werror("Cannot generate subscripted shared from plain type. Use shared[i] or shared.attr");
704  return TRUE;
705}
706
707
708/// blackbox support - destruction
709void countedref_destroyIndexed(blackbox *b, void* ptr)
710{
711  if (ptr) {
712    CountedRefPtr<CountedRefDataIndexed*> data =
713    static_cast<CountedRefDataIndexed*>(ptr);
714    data.release();
715  }
716}
717
718class CountedRefShared:
719  public CountedRef {
720  typedef CountedRefShared self;
721  typedef CountedRef base;
722
723  CountedRefShared(const base& rhs):  base(rhs) { }
724
725public:
726  CountedRefShared(leftv arg):  base(new data_type(arg, FALSE,0)) { }
727
728  /// Construct copy
729  CountedRefShared(const self& rhs): base(rhs) { }
730
731  ~CountedRefShared() { }
732
733  self& operator=(const self& rhs) {
734    return static_cast<self&>(base::operator=(rhs));
735  }
736
737  /// Replace data that reference is pointing to
738  self& operator=(leftv rhs) {
739    return static_cast<self&>(base::operator=(rhs));
740  }
741
742  static self cast(leftv arg) { return base::cast(arg); }
743  static self cast(void* arg) { return base::cast(arg); }
744
745  CountedRefPtr<CountedRefDataIndexed*> subscripted() {
746    return new CountedRefDataIndexed(m_data->idify(), m_data);
747  }
748};
749
750
751
752/// blackbox support - binary operations
753BOOLEAN countedref_Op2Shared(int op, leftv res, leftv head, leftv arg)
754{
755  if  ((op == '[') || (op == '.')) {
756    if (countedref_CheckInit(res, head))  return TRUE;
757    CountedRefPtr<CountedRefDataIndexed*> indexed = CountedRefShared::cast(head).subscripted();
758    if(indexed->operator*().get(head)) return TRUE;
759 
760    if (CountedRef::resolve(arg) || iiExprArith2(res, head, op, arg)) return
761      TRUE;
762
763    if(indexed->retrieve(res)) {
764      indexed.reclaim();
765      res->rtyp = CountedRefEnv::idx_id();
766      res->data = (void *)indexed;
767    }
768    return FALSE;
769  }
770
771  return countedref_Op2(op, res, head, arg);
772}
773
774/// blackbox support - n-ary operations
775BOOLEAN countedref_OpM(int op, leftv res, leftv args)
776{
777  if (args->Data() == NULL) return FALSE;
778
779  if(op == SYSTEM_CMD) {
780    if (args->next) {
781      leftv next = args->next;
782      args->next = NULL;
783      CountedRef obj = CountedRef::cast(args);
784      char* name = (next->Typ() == STRING_CMD? 
785                    (char*) next->Data(): (char*)next->Name());
786      next = next->next;
787      if (next) {
788        if (strcmp(name, "same") == 0) return obj.same(res, next);
789        if (strncmp(name, "like", 4) == 0) return obj.likewise(res, next);
790      }
791      if (strncmp(name, "count", 5) == 0) return obj.count(res);
792      if (strcmp(name, "hash") == 0) return obj.hash(res);
793      if (strcmp(name, "name") == 0) return obj.name(res);
794      if (strncmp(name, "type", 4) == 0) return obj.type(res);
795    }
796    return TRUE;
797  }
798  return CountedRef::cast(args).dereference(args) || iiExprArithM(res, args, op);
799}
800/// blackbox support - assign element
801BOOLEAN countedref_AssignShared(leftv result, leftv arg)
802{
803  /// Case: replace assignment behind reference
804  if ((result->Data()) != NULL) {
805    if (CountedRefShared::resolve(arg)) return TRUE;
806    CountedRefShared::cast(result) = arg;
807    return FALSE;
808  }
809 
810  /// Case: new reference to already shared data
811  if (result->Typ() == arg->Typ()) 
812    return CountedRefShared::cast(arg).outcast(result);
813
814  /// Case: new shared data
815  return CountedRefShared(arg).outcast(result);
816}
817
818/// blackbox support - destruction
819void countedref_destroyShared(blackbox *b, void* ptr)
820{
821  if (ptr) CountedRefShared::cast(ptr).destruct();
822}
823
824void countedref_init() 
825{
826  blackbox *bbx = (blackbox*)omAlloc0(sizeof(blackbox));
827  bbx->blackbox_destroy = countedref_destroy;
828  bbx->blackbox_String  = countedref_String;
829  bbx->blackbox_Print  = countedref_Print;
830  bbx->blackbox_Init    = countedref_Init;
831  bbx->blackbox_Copy    = countedref_Copy;
832  bbx->blackbox_Assign  = countedref_Assign;
833  bbx->blackbox_Op1     = countedref_Op1;
834  bbx->blackbox_Op2     = countedref_Op2;
835  bbx->blackbox_Op3     = countedref_Op3;
836  bbx->blackbox_OpM     = countedref_OpM;
837  bbx->data             = omAlloc0(newstruct_desc_size());
838  CountedRefEnv::ref_id()=setBlackboxStuff(bbx, "reference");
839
840  /// The @c shared type is "inherited" from @c reference.
841  /// It just uses another constructor (to make its own copy of the).
842  blackbox *bbxshared = 
843    (blackbox*)memcpy(omAlloc(sizeof(blackbox)), bbx, sizeof(blackbox));
844  bbxshared->blackbox_Assign  = countedref_AssignShared;
845  bbxshared->blackbox_destroy = countedref_destroyShared;
846  bbxshared->blackbox_Op2     = countedref_Op2Shared;
847  bbxshared->data             = omAlloc0(newstruct_desc_size());
848  CountedRefEnv::sh_id()=setBlackboxStuff(bbxshared, "shared");
849
850  blackbox *bbxindexed = 
851    (blackbox*)memcpy(omAlloc(sizeof(blackbox)), bbx, sizeof(blackbox));
852  bbxindexed->blackbox_destroy = countedref_destroyIndexed;
853  bbxindexed->blackbox_Assign = countedref_AssignIndexed;
854  bbxindexed->data             = omAlloc0(newstruct_desc_size());
855  CountedRefEnv::idx_id()=setBlackboxStuff(bbxindexed, "shared_subexpr");
856
857}
858
859extern "C" { void mod_init() { countedref_init(); } }
860
Note: See TracBrowser for help on using the repository browser.