source: git/Singular/countedref.cc @ 971984c

jengelh-datetimespielwiese
Last change on this file since 971984c was 971984c, checked in by Alexander Dreyer <alexander.dreyer@…>, 10 years ago
Improved interface chg: simplified redundant interface fix: left-hand side of assignment may also be a reference new: M-ary operations for references; def(reference) chg: compile-time de-reference where possible
  • Property mode set to 100644
File size: 8.1 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
35class CountedRef {
36  typedef CountedRef self;
37
38public:
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()); }
52private:
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 **/
65class 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
72public:
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  }
87
88  /// 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  }
115
116  /// @name Reference counter management
117  //@{
118  count_type reclaim() { return ++m_count; }
119  count_type release() { return --m_count; }
120  count_type count() const { return m_count; }
121  //@}
122
123  leftv get () { 
124    leftv result = (leftv)omAlloc0(sizeof(sleftv));
125    get(*result);
126    return result;
127  }
128
129  void get(sleftv& result) {
130    if (m_ring && (m_ring != currRing)) {
131      Werror("Can only use references from current ring.");
132      return;
133    }
134    leftv next = result.next;
135    memcpy(&result, &m_data, sizeof(sleftv));
136    result.next = next;
137  }
138
139private:
140  /// Reference counter
141  count_type m_count;
142
143  /// Singular object
144  sleftv m_data;
145
146  /// Store ring for ring-dependent objects
147  ring m_ring;
148};
149
150class 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();
183    }
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
200class 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
220void* countedref_Init(blackbox*)
221{
222  return NULL;
223}
224
225/// blackbox support - convert to string representation
226void countedref_Print(blackbox *b, void* ptr)
227{
228  if (ptr != NULL) CountedRefCast(ptr)->Print();
229}
230
231/// blackbox support - convert to string representation
232char* countedref_String(blackbox *b, void* ptr)
233{
234  if (ptr != NULL) return CountedRefCast(ptr)->String();
235}
236
237/// blackbox support - copy element
238void* countedref_Copy(blackbox*b, void* ptr)
239{ 
240  if (ptr) static_cast<CountedRefData*>(ptr)->reclaim();
241  return ptr;
242}
243
244/// blackbox support - assign element
245BOOLEAN countedref_Assign(leftv result, leftv arg)
246{
247  // Case: replace assignment behind reference
248  if (result->Data() != NULL)
249    return iiAssign(CountedRefCast(result), CountedRefAccess(arg));
250 
251  // Case: new reference
252  if(arg->rtyp == IDHDL) 
253    return CountedRefData::construct(result, arg);
254 
255  Werror("Can only take reference from identifier");
256  return CountedRefData::set_to(result, NULL, NONE);
257}
258                                                                     
259
260/// blackbox support - unary operations
261BOOLEAN countedref_Op1(int op, leftv res, leftv head)
262{
263  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);
272}
273
274/// blackbox support - binary operations
275BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg)
276{
277  return iiExprArith2(res, CountedRefCast(head), op, CountedRefAccess(arg));
278}
279
280/// blackbox support - ternary operations
281BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2)
282{
283  return iiExprArith3(res, op, CountedRefCast(head), 
284                      CountedRefAccess(arg1), CountedRefAccess(arg2));
285}
286
287
288/// blackbox support - n-ary operations
289BOOLEAN countedref_OpM(int op, leftv res, leftv args)
290{
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);
304}
305
306/// blackbox support - destruction
307void countedref_destroy(blackbox *b, void* ptr)
308{
309  CountedRefData* pRef = static_cast<CountedRefData*>(ptr);
310  if(ptr && !pRef->release())
311    delete pRef;
312}
313
314void countedref_init() 
315{
316  blackbox *bbx = (blackbox*)omAlloc0(sizeof(blackbox));
317  bbx->blackbox_destroy = countedref_destroy;
318  bbx->blackbox_String  = countedref_String;
319  bbx->blackbox_Print  = countedref_Print;
320  bbx->blackbox_Init    = countedref_Init;
321  bbx->blackbox_Copy    = countedref_Copy;
322  bbx->blackbox_Assign  = countedref_Assign;
323  bbx->blackbox_Op1     = countedref_Op1;
324  bbx->blackbox_Op2     = countedref_Op2;
325  bbx->blackbox_Op3     = countedref_Op3;
326  bbx->blackbox_OpM     = countedref_OpM;
327  bbx->data             = omAlloc0(newstruct_desc_size());
328  CountedRef init(*bbx);
329}
330
331extern "C" { void mod_init() { countedref_init(); } }
332
Note: See TracBrowser for help on using the repository browser.