source: git/Singular/countedref.cc @ 6c01d6b

jengelh-datetimespielwiese
Last change on this file since 6c01d6b was 6c01d6b, checked in by Alexander Dreyer <alexander.dreyer@…>, 10 years ago
First version of reference counting running add: first experiment with counted references new: n-ary operations for reference new: more consistent reference operations
  • Property mode set to 100644
File size: 6.5 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 sleftv_shallow {
36  typedef sleftv_shallow self;
37public:
38  sleftv_shallow(sleftv& data): m_data(data) { }
39  sleftv_shallow(const self& rhs): m_data(rhs.m_data) {}
40
41  ~sleftv_shallow() { }// do not need the clean up, do not own
42 
43  leftv operator->() { return *this; }
44  operator leftv() { return &m_data; }
45
46private:
47  sleftv m_data; 
48};
49class ListElementRefData;
50/** @class CountedRefData
51 * This class stores a reference counter as well as a Singular interpreter object.
52 *
53 * It also stores the Singular token number, once per type.
54 **/
55class CountedRefData {
56 typedef CountedRefData self;
57
58  /// Forbit copy construction
59  CountedRefData(const self&);
60  self& operator=(const self&);
61
62public:
63  typedef int id_type;
64  typedef unsigned long count_type;
65
66  /// Construct reference for Singular object
67  CountedRefData(leftv data): m_data(*data), m_count(1) {
68    if (data->e) {
69      m_data.e = (Subexpr)omAlloc0Bin(sSubexpr_bin);
70      memcpy(m_data.e, data->e, sizeof(*m_data.e));
71    }
72  }
73
74  /// Destructor
75  ~CountedRefData()  { if(m_data.e) omFree(m_data.e); };
76
77  sleftv_shallow get() {
78    return sleftv_shallow(m_data);
79  }
80
81  static BOOLEAN construct(leftv res, leftv arg) {
82    return extract(res, (is_ref(arg)? (self*)arg->Data(): new self(arg)), id());
83  }
84
85  static BOOLEAN extract(leftv res, void* data, int op)
86  {
87    if (res->rtyp == IDHDL) {
88      IDDATA((idhdl)res->data) = (char *)data;
89      IDTYP((idhdl)res->data)  = op;
90    }
91    else {
92      res->data = (void *)data;
93      res->rtyp = op;
94    }
95    return (op == NONE? TRUE: FALSE);
96  }
97  /// @name Forward operations
98  //@{
99  BOOLEAN operator()(int op, leftv result, leftv arg){
100      return iiExprArith2(result, get(), op,
101                        (is_ref(arg)? cast(arg).get(): arg));
102   
103  }
104
105  BOOLEAN operator()(int op, leftv result, leftv arg1, leftv arg2) {
106    return iiExprArith3(result, op, get(), 
107                        (is_ref(arg1)? cast(arg1).get(): arg1),
108                        (is_ref(arg2)? cast(arg2).get(): arg2));
109  }
110  //@}
111
112  /// Set Singular type identitfier
113  static void set_id(id_type new_id) {  access_id() = new_id;  }
114
115  /// Get Singular type identitfier
116  static id_type id() { return access_id(); }
117
118  /// Extract Singular interpreter object
119  static self& cast(leftv value, leftv next=NULL) {
120    assume((value != NULL) && is_ref(value));
121    return cast((void*)value->Data(), next);
122  }
123
124  /// Extract reference from Singular interpreter object data
125  static self& cast(void* data, leftv next=NULL) {
126    assume(data != NULL);
127    self* result = static_cast<CountedRefData*>(data);
128    result->m_data.next=next;   /// @todo resolve refs in tail
129    return *result;
130  }
131
132  /// Check for being reference in Singular interpreter object
133  static BOOLEAN is_ref(leftv arg) { return (arg->Typ() == id()); }
134
135  /// @name Reference counter management
136  //@{
137  count_type reclaim() { return ++m_count; }
138  count_type release() { return --m_count; }
139  count_type count() const { return m_count; }
140  //@}
141
142private:
143
144  /// Access identifier (one per class)
145  static id_type& access_id() {
146    static id_type g_id = 0;
147    return g_id;
148  }
149
150  /// Reference counter
151  count_type m_count;
152
153  /// Singular object
154  sleftv m_data;
155};
156
157
158/// blackbox support - initialization
159void* countedref_Init(blackbox*)
160{
161  return NULL;
162}
163
164/// blackbox support - convert to string representation
165void countedref_Print(blackbox *b, void* ptr)
166{
167  CountedRefData::cast(ptr).get()->Print();
168}
169
170/// blackbox support - convert to string representation
171char* countedref_String(blackbox *b, void* ptr)
172{
173  CountedRefData::cast(ptr).get()->String();
174}
175
176/// blackbox support - copy element
177void* countedref_Copy(blackbox*b, void* ptr)
178{ 
179  CountedRefData::cast(ptr).reclaim();
180  return ptr;
181}
182
183/// blackbox support - assign element
184BOOLEAN countedref_Assign(leftv l, leftv r)
185{
186  if (l->Data() == NULL)        // Case: new reference
187  {
188    if(r->rtyp != IDHDL) {
189      Werror("Can only take reference from identifier");
190      return CountedRefData::extract(l, NULL, NONE);
191    }
192    return CountedRefData::construct(l, r);
193  }
194
195  // Case: replace assignment behind reference
196  return iiAssign(CountedRefData::cast(l).get(), r);
197}
198                                                                     
199
200/// blackbox support - unary operations
201BOOLEAN countedref_Op1(int op, leftv res, leftv head)
202{
203  if(op == TYPEOF_CMD)
204    return CountedRefData::extract(res, omStrDup("reference"), STRING_CMD);
205
206  return iiExprArith1(res, CountedRefData::cast(head).get(), op);
207}
208
209/// blackbox support - binary operations
210BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg)
211{
212  return CountedRefData::cast(head)(op, res, arg);
213}
214
215/// blackbox support - ternary operations
216BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2)
217{
218   return CountedRefData::cast(head)(op, res, arg1, arg2);
219}
220
221
222/// blackbox support - n-ary operations
223BOOLEAN countedref_OpM(int op, leftv res, leftv args)
224{
225  return iiExprArithM(res, CountedRefData::cast(args, args->next).get(), op);
226}
227
228/// blackbox support - destruction
229void countedref_destroy(blackbox *b, void* ptr)
230{
231  if (ptr) {
232    CountedRefData* pRef = static_cast<CountedRefData*>(ptr);
233    if(!pRef->release())
234      delete pRef;
235  }
236}
237
238void countedref_init() 
239{
240  blackbox *bbx = (blackbox*)omAlloc0(sizeof(blackbox));
241  bbx->blackbox_destroy = countedref_destroy;
242  bbx->blackbox_String  = countedref_String;
243  bbx->blackbox_Print  = countedref_Print;
244  bbx->blackbox_Init    = countedref_Init;
245  bbx->blackbox_Copy    = countedref_Copy;
246  bbx->blackbox_Assign  = countedref_Assign;
247  bbx->blackbox_Op1     = countedref_Op1;
248  bbx->blackbox_Op2     = countedref_Op2;
249  bbx->blackbox_Op3     = countedref_Op3;
250  bbx->blackbox_OpM     = countedref_OpM;
251  bbx->data             = omAlloc0(newstruct_desc_size());
252  CountedRefData::set_id(setBlackboxStuff(bbx,"reference"));
253}
254
255extern "C" { void mod_init() { countedref_init(); } }
256
Note: See TracBrowser for help on using the repository browser.