source: git/Singular/countedref.cc @ d1fbbf

jengelh-datetimespielwiese
Last change on this file since d1fbbf was d1fbbf, checked in by Alexander Dreyer <alexander.dreyer@…>, 11 years ago
Making autoloading of 'reference' and 'shared' customizable new Added configure option chg Explained more generic CountedRef::is_ref(leftv)
  • Property mode set to 100644
File size: 21.0 KB
Line 
1// -*- c++ -*-
2//*****************************************************************************
3/** @file countedref.cc
4 *
5 * @author Alexander Dreyer
6 * @date 2012-08-15
7 *
8 * This file defines reference countes interpreter objects and adds the
9 * @c blackbox operations for high-level types 'reference' and 'shared'.
10 *
11 * @note This works was supported by the "Industrial Algebra" project.
12 *
13 * @par Copyright:
14 *   (c) 2012 by The Singular Team, see LICENSE file
15**/
16//*****************************************************************************
17
18
19#include "mod2.h"
20#include "ipid.h"
21
22#include "countedref.h"
23
24#include "blackbox.h"
25#include "newstruct.h"
26#include "ipshell.h"
27
28
29/// Overloading ring destruction
30inline void CountedRefPtr_kill(ring r) { rKill(r); }
31
32
33/** @class CountedRefData
34 * This class stores a reference counter as well as a Singular interpreter object.
35 * It also take care of the context, e.g. the current ring, wrap object, etc.
36 **/
37class CountedRefData:
38  public RefCounter {
39  typedef CountedRefData self;
40public:
41  typedef CountedRefWeakPtr<self*> back_ptr;
42private:
43  typedef RefCounter base;
44
45  /// Generate object linked to other reference (e.g. for subscripts)
46  CountedRefData(leftv wrapid, back_ptr back):
47    base(), m_data(wrapid), m_ring(back->m_ring), m_back(back) {
48  }
49
50  /// @name Disallow copying to avoid inconsistence
51  //@{
52  self& operator=(const self&);
53  CountedRefData(const self&);
54  //@}
55
56public:
57  typedef LeftvDeep::copy_tag copy_tag;
58
59  /// Fix smart pointer type to referenced data
60  typedef back_ptr::ptr_type ptr_type;
61
62  /// Fix smart pointer type to ring
63  typedef CountedRefPtr<ring, true> ring_ptr;
64
65  /// Construct shared memory empty Singular object
66  explicit CountedRefData():
67    base(), m_data(), m_ring(), m_back() { }
68
69  /// Reference Singular object
70  explicit CountedRefData(leftv data):
71    base(), m_data(data), m_ring(parent(data)), m_back() { }
72
73  /// Construct reference for Singular object
74  CountedRefData(leftv data, copy_tag do_copy):
75    base(), m_data(data, do_copy), m_ring(parent(data)), m_back() { }
76
77  /// Destruct
78  ~CountedRefData() {
79    if (!m_back.unassigned()) {
80      if (m_back == this)
81        m_back.invalidate();
82      else
83        m_data.clearid(root()); 
84    }
85  }
86
87  /// Generate object for indexing
88  ptr_type wrapid() { return new self(m_data.idify(root()), weakref()); }
89
90  /// Gerenate  weak (but managed) reference to @c *this
91  back_ptr weakref() {
92    if (m_back.unassigned()) 
93      m_back = this;
94    return m_back;
95  }
96  /// Replace with other Singular data
97  self& operator=(leftv rhs) {
98    m_data = rhs;
99    m_ring = parent(rhs);
100    return *this;
101  }
102
103  /// Write (shallow) copy to given handle
104  BOOLEAN put(leftv res) { return broken() || m_data.put(res);  }
105
106  /// Extract (shallow) copy of stored data
107  LeftvShallow operator*() const { return (broken()? LeftvShallow(): (const LeftvShallow&)m_data); }
108
109  /// Determine active ring when ring dependency changes
110  BOOLEAN rering() {
111    if (m_ring ^ m_data.ringed()) m_ring = (m_ring? NULL: currRing);
112    return (m_back && (m_back != this) && m_back->rering());
113  }
114
115  /// Get the current context
116  idhdl* root() { return  (m_ring? &m_ring->idroot: &IDROOT); }
117
118  /// Check whether identifier became invalid
119  BOOLEAN broken() const {
120    if (!m_back.unassigned() && !m_back) 
121      return complain("Back-reference broken");   
122
123    if (m_ring) {
124      if (m_ring != currRing) 
125        return complain("Referenced identifier not from current ring");   
126
127      return m_data.isid()  && m_data.brokenid(currRing->idroot) &&
128        complain("Referenced identifier not available in ring anymore"); 
129    }
130   
131    if (!m_data.isid()) return FALSE;
132    return  m_data.brokenid(IDROOT) &&
133     ((currPack == basePack) ||  m_data.brokenid(basePack->idroot)) &&
134     complain("Referenced identifier not available in current context");
135  }
136
137  /// Reassign actual object
138  BOOLEAN assign(leftv result, leftv arg) { 
139
140    if (!m_data.isid()) {
141      (*this) = arg;
142      return FALSE;
143    }
144    return put(result) || iiAssign(result, arg) || rering();
145  }
146  /// Recover additional information (e.g. subexpression) from likewise object
147  BOOLEAN retrieve(leftv res) { return m_data.retrieve(res); }
148
149  /// Check whether data is all-zero
150  BOOLEAN unassigned() const { return m_data.unassigned(); }
151
152private:
153  /// Raise error message and return @c TRUE
154  BOOLEAN complain(const char* text) const  {
155    Werror(text);
156    return TRUE;
157  }
158
159  /// Store ring for ring-dependent objects
160  static ring parent(leftv rhs) { 
161    return (rhs->RingDependend()? currRing: NULL); 
162  }
163
164protected:
165  /// Singular object
166  LeftvDeep m_data;
167
168  /// Store namespace for ring-dependent objects
169  ring_ptr m_ring;
170
171  /// Reference to actual object for wrap structures 
172  back_ptr m_back;
173};
174
175/// Supporting smart pointer @c CountedRefPtr
176inline void CountedRefPtr_kill(CountedRefData* data) { delete data; }
177
178
179/// blackbox support - initialization
180void* countedref_Init(blackbox*)
181{
182  return NULL;
183}
184
185/// We use the function pointer as a marker of reference types
186/// for CountedRef::is_ref(leftv), see the latter for details
187BOOLEAN countedref_CheckAssign(blackbox *b, leftv L, leftv R)
188{
189  return FALSE;
190}
191
192
193class CountedRef {
194  typedef CountedRef self;
195
196public:
197  /// name type for identifiers
198  typedef int id_type;
199
200  /// Name type for handling referenced data
201  typedef CountedRefData data_type;
202
203  /// Fix smart pointer type to referenced data
204  typedef CountedRefPtr<CountedRefData*> data_ptr;
205
206  /// Check whether argument is already a reference type
207  /// @note We check for the function pointer @c countedref_CheckAssign here,
208  /// that we (ab-)use as a unique marker. This avoids to check a bunch of
209  /// of runtime-varying @c typ IDs for identifying reference-like types.
210  static BOOLEAN is_ref(leftv arg) {
211    int typ = arg->Typ();
212    return ((typ > MAX_TOK) &&
213            (getBlackboxStuff(typ)->blackbox_CheckAssign == countedref_CheckAssign));
214  }
215
216  /// Reference given Singular data 
217  explicit CountedRef(leftv arg):  m_data(new data_type(arg)) { }
218
219protected:
220  /// Recover previously constructed reference
221  CountedRef(data_ptr arg):  m_data(arg) { assume(arg); }
222
223public:
224  /// Construct copy
225  CountedRef(const self& rhs): m_data(rhs.m_data) { }
226
227  /// Replace reference
228  self& operator=(const self& rhs) {
229    m_data = rhs.m_data;
230    return *this;
231  }
232
233  BOOLEAN assign(leftv result, leftv arg) {
234    return m_data->assign(result,arg);
235  }
236
237  /// Extract (shallow) copy of stored data
238  LeftvShallow operator*() { return m_data->operator*(); }
239
240  /// Construct reference data object marked by given identifier number
241  BOOLEAN outcast(leftv res, int typ) {
242    res->rtyp = typ;
243    return outcast(res);
244  }
245
246  /// Construct reference data object from *this
247  BOOLEAN outcast(leftv res) {
248    if (res->rtyp == IDHDL)
249      IDDATA((idhdl)res->data) = (char *)outcast();
250    else
251      res->data = (void *)outcast();
252    return FALSE;
253  }
254
255  /// Construct raw reference data
256  data_type* outcast() { 
257    m_data.reclaim();
258    return m_data;
259  }
260
261  /// Kills a link to the referenced object
262  void destruct() { m_data.release(); }
263
264  /// Kills the link to the referenced object
265  ~CountedRef() { }
266
267  /// Replaces argument by a shallow copy of the references data
268  BOOLEAN dereference(leftv arg) {
269    m_data.reclaim();
270    BOOLEAN b= m_data->put(arg) || ((arg->next != NULL) && resolve(arg->next));
271    m_data.release();
272    return b;
273  }
274
275  /// Check whether object in valid in current context
276  BOOLEAN broken() {return m_data->broken(); }
277
278  /// Check whether (shared) data was initialized but not assigned yet.
279  BOOLEAN unassigned() const { return m_data->unassigned(); }
280
281  /// Get number of references pointing here, too
282  BOOLEAN count(leftv res) { return construct(res, m_data.count() - 1); }
283
284  // Get internal indentifier
285  BOOLEAN enumerate(leftv res) { return construct(res, (long)(data_type*)m_data); }
286
287  /// Check for likewise identifiers
288  BOOLEAN likewise(leftv res, leftv arg) {
289    return resolve(arg) || construct(res, operator*()->data == arg->data); 
290  }
291
292  /// Check for identical reference objects
293  BOOLEAN same(leftv res, leftv arg) { 
294    return construct(res, m_data == arg->Data());
295  }
296
297  /// Get type of references data
298  BOOLEAN type(leftv res) { 
299    return construct(res, Tok2Cmdname(operator*()->Typ()));
300  };
301
302  /// Get (possibly) internal identifier name
303  BOOLEAN name(leftv res) { return construct(res, operator*()->Name()); }
304
305  /// Recover the actual object from raw Singular data
306  static self cast(void* data) {
307    assume(data != NULL);
308    return self(static_cast<data_type*>(data));
309  }
310
311  /// Recover the actual object from Singular interpreter object
312  static self cast(leftv arg) {
313    assume(arg != NULL); assume(is_ref(arg));
314    return self::cast(arg->Data());
315  }
316
317  /// If necessary dereference.
318  static BOOLEAN resolve(leftv arg) {
319    assume(arg != NULL);
320    while (is_ref(arg)) { if(CountedRef::cast(arg).dereference(arg)) return TRUE; };
321    return (arg->next != NULL) && resolve(arg->next);
322  }
323
324  /// Construct integer value
325  static BOOLEAN construct(leftv res, long data) {
326    res->data = (void*) data;
327    res->rtyp = INT_CMD;
328    return FALSE;
329  }
330
331  /// Construct string
332  static BOOLEAN construct(leftv res, const char* data) {
333    res->data = (void*)omStrDup(data);
334    res->rtyp = STRING_CMD;
335    return FALSE;
336  }
337  /// Construct void-style object
338  static BOOLEAN construct(leftv res) {
339    res->data = NULL;
340    res->rtyp = NONE;
341    return FALSE;
342  }
343
344protected:
345  /// Store pointer to actual data
346  data_ptr m_data;
347};
348
349/// blackbox support - convert to string representation
350void countedref_Print(blackbox *b, void* ptr)
351{
352  if (ptr) (*CountedRef::cast(ptr))->Print();
353  else PrintS("<unassigned reference or shared memory>");
354}
355
356/// blackbox support - convert to string representation
357char* countedref_String(blackbox *b, void* ptr)
358{
359  if (ptr == NULL) return omStrDup(sNoName);
360  return (*CountedRef::cast(ptr))->String();
361}
362
363/// blackbox support - copy element
364void* countedref_Copy(blackbox*b, void* ptr)
365{ 
366  if (ptr) return CountedRef::cast(ptr).outcast();
367  return NULL;
368}
369
370/// blackbox support - assign element
371BOOLEAN countedref_Assign(leftv result, leftv arg)
372{
373  // Case: replace assignment behind reference
374  if (result->Data() != NULL) {
375    CountedRef ref = CountedRef::cast(result);
376    return CountedRef::resolve(arg) || ref.assign(result, arg); 
377  }
378 
379  // Case: copy reference
380  if (result->Typ() == arg->Typ())
381    return CountedRef::cast(arg).outcast(result);
382
383  // Case: new reference
384  if ((arg->rtyp == IDHDL) || CountedRef::is_ref(arg))
385    return CountedRef(arg).outcast(result);
386
387  Werror("Can only take reference from identifier");
388  return TRUE;
389}
390
391BOOLEAN countedref_CheckInit(leftv res, leftv arg)
392{
393  if (arg->Data() != NULL) return FALSE;
394  res->rtyp = NONE;
395  Werror("Noninitialized access");
396  return TRUE;
397}
398                                                                 
399/// blackbox support - unary operations
400BOOLEAN countedref_Op1(int op, leftv res, leftv head)
401{
402  if(op == TYPEOF_CMD)
403    return blackboxDefaultOp1(op, res, head);
404
405  if (countedref_CheckInit(res, head)) return TRUE;
406 
407  if ((op == DEF_CMD) || (op == head->Typ())) {
408    res->rtyp = head->Typ();
409    return iiAssign(res, head);
410  }
411
412  CountedRef ref = CountedRef::cast(head);
413  return ref.dereference(head) ||
414    iiExprArith1(res, head, op == LINK_CMD? head->Typ(): op);
415}
416
417
418
419/// blackbox support - binary operations (resolve seocnd argument)
420static BOOLEAN countedref_Op2_(int op, leftv res, leftv head, leftv arg)
421{
422  if (CountedRef::is_ref(arg)) {
423    CountedRef ref = CountedRef::cast(arg);
424    return ref.dereference(arg) || iiExprArith2(res, head, op, arg);
425  }
426  return  iiExprArith2(res, head, op, arg);
427}
428
429BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg)
430{
431  if (countedref_CheckInit(res, head)) return TRUE;
432  if (CountedRef::is_ref(head)) {
433    CountedRef ref = CountedRef::cast(head);
434    return ref.dereference(head) || countedref_Op2_(op, res, head, arg);
435  }
436  return countedref_Op2_(op, res, head, arg);
437}
438
439static BOOLEAN countedref_Op3__(int op, leftv res, leftv head, leftv arg1, leftv arg2)
440{
441
442  if (CountedRef::is_ref(arg2)) {
443    CountedRef ref = CountedRef::cast(arg2);
444    return ref.dereference(arg2) || iiExprArith3(res, op, head, arg1, arg2);
445  }
446  return iiExprArith3(res, op, head, arg1, arg2);
447}
448
449static BOOLEAN countedref_Op3_(int op, leftv res, leftv head, leftv arg1, leftv arg2)
450{
451  if (CountedRef::is_ref(arg1)) {
452    CountedRef ref = CountedRef::cast(arg1);
453    return ref.dereference(arg1) || countedref_Op3__(op, res, head, arg1, arg2);
454  }
455  return countedref_Op3__(op, res, head, arg1, arg2);
456}
457
458
459/// blackbox support - ternary operations
460BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2)
461{
462  if (countedref_CheckInit(res, head)) return TRUE;
463  if (CountedRef::is_ref(head)) {
464    CountedRef ref = CountedRef::cast(head);
465    return ref.dereference(head) || countedref_Op3_(op, res, head, arg1, arg2);
466  }
467  return countedref_Op3_(op, res, head, arg1, arg2);
468}
469
470
471/// blackbox support - destruction
472void countedref_destroy(blackbox *b, void* ptr)
473{
474  if (ptr) CountedRef::cast(ptr).destruct();
475}
476
477
478class CountedRefShared:
479  public CountedRef {
480  typedef CountedRefShared self;
481  typedef CountedRef base;
482
483  /// Reinterprete @c CountedRef as @c CountedRefShared
484  CountedRefShared(const base& rhs):  base(rhs) { }
485
486  /// Generate from data pointer
487  CountedRefShared(data_ptr rhs):  base(rhs) { }
488
489public:
490  /// Default constructor for initialized, but all-zero, shared data object
491  CountedRefShared():  base(new data_type) { }
492
493  /// Construct internal copy of Singular interpreter object
494  explicit CountedRefShared(leftv arg):  base(new data_type(arg, data_type::copy_tag())) { }
495
496  /// Construct new reference to internal data
497  CountedRefShared(const self& rhs): base(rhs) { }
498
499  /// Desctruct
500  ~CountedRefShared() { }
501
502  /// Change reference to shared data
503  self& operator=(const self& rhs) {
504    return static_cast<self&>(base::operator=(rhs));
505  }
506
507  /// Recovering outcasted @c CountedRefShared object from interpreter object
508  static self cast(leftv arg) { return base::cast(arg); }
509
510  /// Recovering outcasted @c CountedRefShared object from raw data
511  static self cast(void* arg) { return base::cast(arg); }
512
513  /// Temporarily wrap with identifier for '[' and '.' operation
514  self wrapid() { return self(m_data->wrapid()); }
515
516  /// Generate weak reference (may get invalid)
517  data_type::back_ptr weakref() { return m_data->weakref(); }
518
519  /// Recover more information (e.g. subexpression data) from computed result
520  BOOLEAN retrieve(leftv res, int typ) { 
521    return (m_data->retrieve(res) && outcast(res, typ));
522  }
523};
524
525/// Blackbox support - generate initialized, but all-zero - shared data
526void* countedref_InitShared(blackbox*)
527{
528  return CountedRefShared().outcast();
529}
530
531/// Blackbox support - unary operation for shared data
532BOOLEAN countedref_Op1Shared(int op, leftv res, leftv head)
533{
534  if(op == TYPEOF_CMD)
535    return blackboxDefaultOp1(op, res, head);
536
537  if (countedref_CheckInit(res, head)) return TRUE;
538
539  if ((op == DEF_CMD) || (op == head->Typ())) {
540    res->rtyp = head->Typ();
541    return iiAssign(res, head);
542  }
543
544  CountedRefShared ref = CountedRefShared::cast(head);
545
546  if ((op == LINK_CMD) ) {
547    if (ref.dereference(head)) return TRUE;
548    res->Copy(head);
549    return (res->Typ() == NONE);
550  }
551
552  CountedRefShared wrap = ref.wrapid();
553  int typ = head->Typ();
554  return wrap.dereference(head) || iiExprArith1(res, head, op) ||
555    wrap.retrieve(res, typ);
556}
557
558
559/// blackbox support - binary operations
560BOOLEAN countedref_Op2Shared(int op, leftv res, leftv head, leftv arg)
561{
562  if (countedref_CheckInit(res, head))  return TRUE;
563
564  if (CountedRefShared::is_ref(head)) {
565    CountedRefShared wrap = CountedRefShared::cast(head).wrapid();
566    int typ = head->Typ();
567    return wrap.dereference(head) || countedref_Op2_(op, res, head, arg) ||
568      wrap.retrieve(res, typ);
569  }
570
571  return countedref_Op2_(op, res, head, arg);
572}
573
574/// blackbox support - n-ary operations
575BOOLEAN countedref_OpM(int op, leftv res, leftv args)
576{
577  if (args->Data() == NULL) return FALSE;
578
579  if(op == SYSTEM_CMD) {
580    if (args->next) {
581      leftv next = args->next;
582      args->next = NULL;
583
584      char* name = (next->Typ() == STRING_CMD? 
585                    (char*) next->Data(): (char*)next->Name());
586      next = next->next;
587
588      if (strcmp(name, "help") == 0) {
589        PrintS("system(<ref>, ...): extended functionality for reference/shared data <ref>\n");
590        PrintS("  system(<ref>, count)         - number of references pointing to <ref>\n");
591        PrintS("  system(<ref>, enumerate)     - unique number for identifying <ref>\n");
592        PrintS("  system(<ref>, undefined)     - checks whether <ref> had been assigned\n");
593        PrintS("  system(<ref>, \"help\")        - prints this information message\n");
594        PrintS("  system(<ref>, \"typeof\")      - actual type referenced by <ref>\n");
595        PrintS("  system(<ref1>, same, <ref2>) - tests for identic reference objects\n");
596        return CountedRef::construct(res);
597      }
598      if (strncmp(name, "undef", 5) == 0) {
599        return CountedRef::construct(res, args->Data()? 
600                          (CountedRef::cast(args).unassigned()? 1: 2): 0);
601      }
602
603      CountedRef obj = CountedRef::cast(args);
604      if (next) {
605        if (strcmp(name, "same") == 0) return obj.same(res, next);
606        // likewise may be hard to interprete, so we not not document it above
607        if (strncmp(name, "like", 4) == 0) return obj.likewise(res, next); 
608      }
609      if (strncmp(name, "count", 5) == 0) return obj.count(res);
610      if (strncmp(name, "enum", 4) == 0) return obj.enumerate(res);
611      if (strcmp(name, "name") == 0) return obj.name(res); // undecumented
612      if (strncmp(name, "typ", 3) == 0) return obj.type(res);
613    }
614    return TRUE;
615  }
616  if (op == LIST_CMD){
617    res->rtyp = op;
618    return jjLIST_PL(res, args);
619  }
620  CountedRef ref = CountedRef::cast(args);
621  return ref.dereference(args) || iiExprArithM(res, args, op);
622}
623
624/// blackbox support - assign element
625BOOLEAN countedref_AssignShared(leftv result, leftv arg)
626{
627  /// Case: replace assignment behind reference
628  if ((result->Data() != NULL)  && !CountedRefShared::cast(result).unassigned()) {
629    CountedRef ref = CountedRef::cast(result);
630    return CountedRef::resolve(arg) || ref.assign(result, arg); 
631  }
632 
633  /// Case: new reference to already shared data
634  if (result->Typ() == arg->Typ()) {
635    if (result->Data() != NULL) 
636      CountedRefShared::cast(result).destruct();
637    return CountedRefShared::cast(arg).outcast(result);
638  } 
639  if(CountedRefShared::cast(result).unassigned()) {
640   return CountedRefShared::cast(result).assign(result, arg);
641
642    return FALSE;
643  }
644   
645  /// Case: new shared data
646  return CountedRefShared(arg).outcast(result);
647}
648
649/// blackbox support - destruction
650void countedref_destroyShared(blackbox *b, void* ptr)
651{
652  if (ptr) CountedRefShared::cast(ptr).destruct();
653}
654
655
656BOOLEAN countedref_serialize(blackbox *b, void *d, si_link f)
657{
658  sleftv l;
659  memset(&l,0,sizeof(l));
660  l.rtyp = STRING_CMD;
661  l.data = (void*)omStrDup("shared"); // references are converted
662  f->m->Write(f, &l);
663  CountedRefShared::cast(d).dereference(&l);
664  f->m->Write(f, &l);
665  return FALSE;
666}
667
668BOOLEAN countedref_deserialize(blackbox **b, void **d, si_link f)
669{
670  // rtyp must be set correctly (to the blackbox id) by routine calling
671  leftv data=f->m->Read(f);
672  CountedRefShared sh(data);
673  *d = sh.outcast();
674  return FALSE;
675}
676
677void countedref_reference_load()
678{
679  blackbox *bbx = (blackbox*)omAlloc0(sizeof(blackbox));
680  bbx->blackbox_CheckAssign = countedref_CheckAssign;
681  bbx->blackbox_destroy = countedref_destroy;
682  bbx->blackbox_String  = countedref_String;
683  bbx->blackbox_Print  = countedref_Print;
684  bbx->blackbox_Init    = countedref_Init;
685  bbx->blackbox_Copy    = countedref_Copy;
686  bbx->blackbox_Assign  = countedref_Assign;
687  bbx->blackbox_Op1     = countedref_Op1;
688  bbx->blackbox_Op2     = countedref_Op2;
689  bbx->blackbox_Op3     = countedref_Op3;
690  bbx->blackbox_OpM     = countedref_OpM;
691  bbx->blackbox_serialize   = countedref_serialize;
692  bbx->blackbox_deserialize = countedref_deserialize;
693  bbx->data             = omAlloc0(newstruct_desc_size());
694  setBlackboxStuff(bbx, "reference");
695}
696
697void countedref_shared_load()
698{
699  blackbox *bbxshared = (blackbox*)omAlloc0(sizeof(blackbox));
700  bbxshared->blackbox_String  = countedref_String;
701  bbxshared->blackbox_Print  = countedref_Print;
702  bbxshared->blackbox_Copy    = countedref_Copy;
703  bbxshared->blackbox_Op3     = countedref_Op3;
704  bbxshared->blackbox_OpM     = countedref_OpM;
705  bbxshared->blackbox_serialize   = countedref_serialize;
706  bbxshared->blackbox_deserialize = countedref_deserialize;
707
708  bbxshared->blackbox_CheckAssign = countedref_CheckAssign;
709  bbxshared->blackbox_Assign  = countedref_AssignShared;
710  bbxshared->blackbox_destroy = countedref_destroyShared;
711  bbxshared->blackbox_Op1     = countedref_Op1Shared;
712  bbxshared->blackbox_Op2     = countedref_Op2Shared;
713  bbxshared->blackbox_Init    = countedref_InitShared;
714  bbxshared->data             = omAlloc0(newstruct_desc_size());
715  setBlackboxStuff(bbxshared, "shared");
716}
717
718
Note: See TracBrowser for help on using the repository browser.