source: git/Singular/countedref.cc @ bd8204

spielwiese
Last change on this file since bd8204 was bd8204, checked in by Alexander Dreyer <adreyer@…>, 11 years ago
Using blackbox-functionality to check whther type was already loaded
  • 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 <kernel/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  {
156    WerrorS(text);
157    return TRUE;
158  }
159
160  /// Store ring for ring-dependent objects
161  static ring parent(leftv rhs)
162  {
163    return (rhs->RingDependend()? currRing: NULL);
164  }
165
166protected:
167  /// Singular object
168  LeftvDeep m_data;
169
170  /// Store namespace for ring-dependent objects
171  ring_ptr m_ring;
172
173  /// Reference to actual object for wrap structures
174  back_ptr m_back;
175};
176
177/// Supporting smart pointer @c CountedRefPtr
178inline void CountedRefPtr_kill(CountedRefData* data) { delete data; }
179
180
181/// blackbox support - initialization
182void* countedref_Init(blackbox*)
183{
184  return NULL;
185}
186
187/// We use the function pointer as a marker of reference types
188/// for CountedRef::is_ref(leftv), see the latter for details
189BOOLEAN countedref_CheckAssign(blackbox *b, leftv L, leftv R)
190{
191  return FALSE;
192}
193
194
195class CountedRef {
196  typedef CountedRef self;
197
198public:
199  /// name type for identifiers
200  typedef int id_type;
201
202  /// Name type for handling referenced data
203  typedef CountedRefData data_type;
204
205  /// Fix smart pointer type to referenced data
206  typedef CountedRefPtr<CountedRefData*> data_ptr;
207
208  /// Check whether argument is already a reference type
209  /// @note We check for the function pointer @c countedref_CheckAssign here,
210  /// that we (ab-)use as a unique marker. This avoids to check a bunch of
211  /// of runtime-varying @c typ IDs for identifying reference-like types.
212  static BOOLEAN is_ref(leftv arg) {
213    int typ = arg->Typ();
214    return ((typ > MAX_TOK) &&
215            (getBlackboxStuff(typ)->blackbox_CheckAssign == countedref_CheckAssign));
216  }
217
218  /// Reference given Singular data
219  explicit CountedRef(leftv arg):  m_data(new data_type(arg)) { }
220
221protected:
222  /// Recover previously constructed reference
223  CountedRef(data_ptr arg):  m_data(arg) { assume(arg); }
224
225public:
226  /// Construct copy
227  CountedRef(const self& rhs): m_data(rhs.m_data) { }
228
229  /// Replace reference
230  self& operator=(const self& rhs) {
231    m_data = rhs.m_data;
232    return *this;
233  }
234
235  BOOLEAN assign(leftv result, leftv arg) {
236    return m_data->assign(result,arg);
237  }
238
239  /// Extract (shallow) copy of stored data
240  LeftvShallow operator*() { return m_data->operator*(); }
241
242  /// Construct reference data object marked by given identifier number
243  BOOLEAN outcast(leftv res, int typ) {
244    res->rtyp = typ;
245    return outcast(res);
246  }
247
248  /// Construct reference data object from *this
249  BOOLEAN outcast(leftv res) {
250    if (res->rtyp == IDHDL)
251      IDDATA((idhdl)res->data) = (char *)outcast();
252    else
253      res->data = (void *)outcast();
254    return FALSE;
255  }
256
257  /// Construct raw reference data
258  data_type* outcast() {
259    m_data.reclaim();
260    return m_data;
261  }
262
263  /// Kills a link to the referenced object
264  void destruct() { m_data.release(); }
265
266  /// Kills the link to the referenced object
267  ~CountedRef() { }
268
269  /// Replaces argument by a shallow copy of the references data
270  BOOLEAN dereference(leftv arg) {
271    m_data.reclaim();
272    BOOLEAN b= m_data->put(arg) || ((arg->next != NULL) && resolve(arg->next));
273    m_data.release();
274    return b;
275  }
276
277  /// Check whether object in valid in current context
278  BOOLEAN broken() {return m_data->broken(); }
279
280  /// Check whether (shared) data was initialized but not assigned yet.
281  BOOLEAN unassigned() const { return m_data->unassigned(); }
282
283  /// Get number of references pointing here, too
284  BOOLEAN count(leftv res) { return construct(res, m_data.count() - 1); }
285
286  // Get internal indentifier
287  BOOLEAN enumerate(leftv res) { return construct(res, (long)(data_type*)m_data); }
288
289  /// Check for likewise identifiers
290  BOOLEAN likewise(leftv res, leftv arg) {
291    return resolve(arg) || construct(res, operator*()->data == arg->data);
292  }
293
294  /// Check for identical reference objects
295  BOOLEAN same(leftv res, leftv arg) {
296    return construct(res, m_data == arg->Data());
297  }
298
299  /// Get type of references data
300  BOOLEAN type(leftv res) {
301    return construct(res, Tok2Cmdname(operator*()->Typ()));
302  };
303
304  /// Get (possibly) internal identifier name
305  BOOLEAN name(leftv res) { return construct(res, operator*()->Name()); }
306
307  /// Recover the actual object from raw Singular data
308  static self cast(void* data) {
309    assume(data != NULL);
310    return self(static_cast<data_type*>(data));
311  }
312
313  /// Recover the actual object from Singular interpreter object
314  static self cast(leftv arg) {
315    assume(arg != NULL); assume(is_ref(arg));
316    return self::cast(arg->Data());
317  }
318
319  /// If necessary dereference.
320  static BOOLEAN resolve(leftv arg) {
321    assume(arg != NULL);
322    while (is_ref(arg)) { if(CountedRef::cast(arg).dereference(arg)) return TRUE; };
323    return (arg->next != NULL) && resolve(arg->next);
324  }
325
326  /// Construct integer value
327  static BOOLEAN construct(leftv res, long data) {
328    res->data = (void*) data;
329    res->rtyp = INT_CMD;
330    return FALSE;
331  }
332
333  /// Construct string
334  static BOOLEAN construct(leftv res, const char* data) {
335    res->data = (void*)omStrDup(data);
336    res->rtyp = STRING_CMD;
337    return FALSE;
338  }
339  /// Construct void-style object
340  static BOOLEAN construct(leftv res) {
341    res->data = NULL;
342    res->rtyp = NONE;
343    return FALSE;
344  }
345
346protected:
347  /// Store pointer to actual data
348  data_ptr m_data;
349};
350
351/// blackbox support - convert to string representation
352void countedref_Print(blackbox *b, void* ptr)
353{
354  if (ptr) (*CountedRef::cast(ptr))->Print();
355  else PrintS("<unassigned reference or shared memory>");
356}
357
358/// blackbox support - convert to string representation
359char* countedref_String(blackbox *b, void* ptr)
360{
361  if (ptr == NULL) return omStrDup(sNoName);
362  return (*CountedRef::cast(ptr))->String();
363}
364
365/// blackbox support - copy element
366void* countedref_Copy(blackbox*b, void* ptr)
367{
368  if (ptr) return CountedRef::cast(ptr).outcast();
369  return NULL;
370}
371
372/// blackbox support - assign element
373BOOLEAN countedref_Assign(leftv result, leftv arg)
374{
375  // Case: replace assignment behind reference
376  if (result->Data() != NULL) {
377    CountedRef ref = CountedRef::cast(result);
378    return CountedRef::resolve(arg) || ref.assign(result, arg);
379  }
380
381  // Case: copy reference
382  if (result->Typ() == arg->Typ())
383    return CountedRef::cast(arg).outcast(result);
384
385  // Case: new reference
386  if ((arg->rtyp == IDHDL) || CountedRef::is_ref(arg))
387    return CountedRef(arg).outcast(result);
388
389  WerrorS("Can only take reference from identifier");
390  return TRUE;
391}
392
393BOOLEAN countedref_CheckInit(leftv res, leftv arg)
394{
395  if (arg->Data() != NULL) return FALSE;
396  res->rtyp = NONE;
397  WerrorS("Noninitialized access");
398  return TRUE;
399}
400
401/// blackbox support - unary operations
402BOOLEAN countedref_Op1(int op, leftv res, leftv head)
403{
404  if(op == TYPEOF_CMD)
405    return blackboxDefaultOp1(op, res, head);
406
407  if (countedref_CheckInit(res, head)) return TRUE;
408
409  if ((op == DEF_CMD) || (op == head->Typ()))
410  {
411    res->rtyp = head->Typ();
412    return iiAssign(res, head);
413  }
414
415  CountedRef ref = CountedRef::cast(head);
416  return ref.dereference(head) ||
417    iiExprArith1(res, head, op == LINK_CMD? head->Typ(): op);
418}
419
420
421
422/// blackbox support - binary operations (resolve seocnd argument)
423static BOOLEAN countedref_Op2_(int op, leftv res, leftv head, leftv arg)
424{
425  if (CountedRef::is_ref(arg))
426  {
427    CountedRef ref = CountedRef::cast(arg);
428    return ref.dereference(arg) || iiExprArith2(res, head, op, arg);
429  }
430  return  iiExprArith2(res, head, op, arg);
431}
432
433BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg)
434{
435  if (countedref_CheckInit(res, head)) return TRUE;
436  if (CountedRef::is_ref(head))
437  {
438    CountedRef ref = CountedRef::cast(head);
439    return ref.dereference(head) || countedref_Op2_(op, res, head, arg);
440  }
441  return countedref_Op2_(op, res, head, arg);
442}
443
444static BOOLEAN countedref_Op3__(int op, leftv res, leftv head, leftv arg1, leftv arg2)
445{
446
447  if (CountedRef::is_ref(arg2))
448  {
449    CountedRef ref = CountedRef::cast(arg2);
450    return ref.dereference(arg2) || iiExprArith3(res, op, head, arg1, arg2);
451  }
452  return iiExprArith3(res, op, head, arg1, arg2);
453}
454
455static BOOLEAN countedref_Op3_(int op, leftv res, leftv head, leftv arg1, leftv arg2)
456{
457  if (CountedRef::is_ref(arg1))
458  {
459    CountedRef ref = CountedRef::cast(arg1);
460    return ref.dereference(arg1) || countedref_Op3__(op, res, head, arg1, arg2);
461  }
462  return countedref_Op3__(op, res, head, arg1, arg2);
463}
464
465
466/// blackbox support - ternary operations
467BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2)
468{
469  if (countedref_CheckInit(res, head)) return TRUE;
470  if (CountedRef::is_ref(head))
471  {
472    CountedRef ref = CountedRef::cast(head);
473    return ref.dereference(head) || countedref_Op3_(op, res, head, arg1, arg2);
474  }
475  return countedref_Op3_(op, res, head, arg1, arg2);
476}
477
478
479/// blackbox support - destruction
480void countedref_destroy(blackbox *b, void* ptr)
481{
482  if (ptr) CountedRef::cast(ptr).destruct();
483}
484
485
486class CountedRefShared:
487  public CountedRef
488  {
489  typedef CountedRefShared self;
490  typedef CountedRef base;
491
492  /// Reinterprete @c CountedRef as @c CountedRefShared
493  CountedRefShared(const base& rhs):  base(rhs) { }
494
495  /// Generate from data pointer
496  CountedRefShared(data_ptr rhs):  base(rhs) { }
497
498public:
499  /// Default constructor for initialized, but all-zero, shared data object
500  CountedRefShared():  base(new data_type) { }
501
502  /// Construct internal copy of Singular interpreter object
503  explicit CountedRefShared(leftv arg):  base(new data_type(arg, data_type::copy_tag())) { }
504
505  /// Construct new reference to internal data
506  CountedRefShared(const self& rhs): base(rhs) { }
507
508  /// Desctruct
509  ~CountedRefShared() { }
510
511  /// Change reference to shared data
512  self& operator=(const self& rhs) {
513    return static_cast<self&>(base::operator=(rhs));
514  }
515
516  /// Recovering outcasted @c CountedRefShared object from interpreter object
517  static self cast(leftv arg) { return base::cast(arg); }
518
519  /// Recovering outcasted @c CountedRefShared object from raw data
520  static self cast(void* arg) { return base::cast(arg); }
521
522  /// Temporarily wrap with identifier for '[' and '.' operation
523  self wrapid() { return self(m_data->wrapid()); }
524
525  /// Generate weak reference (may get invalid)
526  data_type::back_ptr weakref() { return m_data->weakref(); }
527
528  /// Recover more information (e.g. subexpression data) from computed result
529  BOOLEAN retrieve(leftv res, int typ)
530  {
531    return (m_data->retrieve(res) && outcast(res, typ));
532  }
533};
534
535/// Blackbox support - generate initialized, but all-zero - shared data
536void* countedref_InitShared(blackbox*)
537{
538  return CountedRefShared().outcast();
539}
540
541/// Blackbox support - unary operation for shared data
542BOOLEAN countedref_Op1Shared(int op, leftv res, leftv head)
543{
544  if(op == TYPEOF_CMD)
545    return blackboxDefaultOp1(op, res, head);
546
547  if (countedref_CheckInit(res, head)) return TRUE;
548
549  if ((op == DEF_CMD) || (op == head->Typ()))
550  {
551    res->rtyp = head->Typ();
552    return iiAssign(res, head);
553  }
554
555  CountedRefShared ref = CountedRefShared::cast(head);
556
557  if (op == LINK_CMD)
558  {
559    if (ref.dereference(head)) return TRUE;
560    res->Copy(head);
561    return (res->Typ() == NONE);
562  }
563
564  CountedRefShared wrap = ref.wrapid();
565  int typ = head->Typ();
566  return wrap.dereference(head) || iiExprArith1(res, head, op) ||
567    wrap.retrieve(res, typ);
568}
569
570
571/// blackbox support - binary operations
572BOOLEAN countedref_Op2Shared(int op, leftv res, leftv head, leftv arg)
573{
574  if (countedref_CheckInit(res, head))  return TRUE;
575
576  if (CountedRefShared::is_ref(head))
577  {
578    CountedRefShared wrap = CountedRefShared::cast(head).wrapid();
579    int typ = head->Typ();
580    return wrap.dereference(head) || countedref_Op2_(op, res, head, arg) ||
581      wrap.retrieve(res, typ);
582  }
583
584  return countedref_Op2_(op, res, head, arg);
585}
586
587/// blackbox support - n-ary operations
588BOOLEAN countedref_OpM(int op, leftv res, leftv args)
589{
590  if (args->Data() == NULL) return FALSE;
591
592  if(op == SYSTEM_CMD)
593  {
594    if (args->next)
595    {
596      leftv next = args->next;
597      args->next = NULL;
598
599      char* name = (next->Typ() == STRING_CMD?
600                    (char*) next->Data(): (char*)next->Name());
601      next = next->next;
602
603      if (strcmp(name, "help") == 0)
604      {
605        PrintS("system(<ref>, ...): extended functionality for reference/shared data <ref>\n");
606        PrintS("  system(<ref>, count)         - number of references pointing to <ref>\n");
607        PrintS("  system(<ref>, enumerate)     - unique number for identifying <ref>\n");
608        PrintS("  system(<ref>, undefined)     - checks whether <ref> had been assigned\n");
609        PrintS("  system(<ref>, \"help\")        - prints this information message\n");
610        PrintS("  system(<ref>, \"typeof\")      - actual type referenced by <ref>\n");
611        PrintS("  system(<ref1>, same, <ref2>) - tests for identic reference objects\n");
612        return CountedRef::construct(res);
613      }
614      if (strncmp(name, "undef", 5) == 0)
615      {
616        return CountedRef::construct(res, args->Data()?
617                          (CountedRef::cast(args).unassigned()? 1: 2): 0);
618      }
619
620      CountedRef obj = CountedRef::cast(args);
621      if (next)
622      {
623        if (strcmp(name, "same") == 0) return obj.same(res, next);
624        // likewise may be hard to interprete, so we not not document it above
625        if (strncmp(name, "like", 4) == 0) return obj.likewise(res, next);
626      }
627      if (strncmp(name, "count", 5) == 0) return obj.count(res);
628      if (strncmp(name, "enum", 4) == 0) return obj.enumerate(res);
629      if (strcmp(name, "name") == 0) return obj.name(res); // undecumented
630      if (strncmp(name, "typ", 3) == 0) return obj.type(res);
631    }
632    return TRUE;
633  }
634  if (op == LIST_CMD)
635  {
636    res->rtyp = op;
637    return jjLIST_PL(res, args);
638  }
639  CountedRef ref = CountedRef::cast(args);
640  return ref.dereference(args) || iiExprArithM(res, args, op);
641}
642
643/// blackbox support - assign element
644BOOLEAN countedref_AssignShared(leftv result, leftv arg)
645{
646  /// Case: replace assignment behind reference
647  if ((result->Data() != NULL)  && !CountedRefShared::cast(result).unassigned()) {
648    CountedRef ref = CountedRef::cast(result);
649    return CountedRef::resolve(arg) || ref.assign(result, arg);
650  }
651
652  /// Case: new reference to already shared data
653  if (result->Typ() == arg->Typ())
654  {
655    if (result->Data() != NULL)
656      CountedRefShared::cast(result).destruct();
657    return CountedRefShared::cast(arg).outcast(result);
658  }
659  if(CountedRefShared::cast(result).unassigned())
660  {
661    return CountedRefShared::cast(result).assign(result, arg);
662  }
663
664  /// Case: new shared data
665  return CountedRefShared(arg).outcast(result);
666}
667
668/// blackbox support - destruction
669void countedref_destroyShared(blackbox *b, void* ptr)
670{
671  if (ptr) CountedRefShared::cast(ptr).destruct();
672}
673
674
675BOOLEAN countedref_serialize(blackbox *b, void *d, si_link f)
676{
677  sleftv l;
678  memset(&l,0,sizeof(l));
679  l.rtyp = STRING_CMD;
680  l.data = (void*)omStrDup("shared"); // references are converted
681  f->m->Write(f, &l);
682  CountedRefShared::cast(d).dereference(&l);
683  f->m->Write(f, &l);
684  return FALSE;
685}
686
687BOOLEAN countedref_deserialize(blackbox **b, void **d, si_link f)
688{
689  // rtyp must be set correctly (to the blackbox id) by routine calling
690  leftv data=f->m->Read(f);
691  CountedRefShared sh(data);
692  *d = sh.outcast();
693  return FALSE;
694}
695
696void countedref_reference_load()
697{
698  int tok;
699  if (blackboxIsCmd("reference", tok) == ROOT_DECL)
700    return;
701
702  blackbox *bbx = (blackbox*)omAlloc0(sizeof(blackbox));
703  bbx->blackbox_CheckAssign = countedref_CheckAssign;
704  bbx->blackbox_destroy = countedref_destroy;
705  bbx->blackbox_String  = countedref_String;
706  bbx->blackbox_Print  = countedref_Print;
707  bbx->blackbox_Init    = countedref_Init;
708  bbx->blackbox_Copy    = countedref_Copy;
709  bbx->blackbox_Assign  = countedref_Assign;
710  bbx->blackbox_Op1     = countedref_Op1;
711  bbx->blackbox_Op2     = countedref_Op2;
712  bbx->blackbox_Op3     = countedref_Op3;
713  bbx->blackbox_OpM     = countedref_OpM;
714  bbx->blackbox_serialize   = countedref_serialize;
715  bbx->blackbox_deserialize = countedref_deserialize;
716  bbx->data             = omAlloc0(newstruct_desc_size());
717  setBlackboxStuff(bbx, "reference");
718}
719
720void countedref_shared_load()
721{
722  int tok;
723  if (blackboxIsCmd("shared", tok) == ROOT_DECL)
724    return;
725
726  blackbox *bbxshared = (blackbox*)omAlloc0(sizeof(blackbox));
727  bbxshared->blackbox_String  = countedref_String;
728  bbxshared->blackbox_Print  = countedref_Print;
729  bbxshared->blackbox_Copy    = countedref_Copy;
730  bbxshared->blackbox_Op3     = countedref_Op3;
731  bbxshared->blackbox_OpM     = countedref_OpM;
732  bbxshared->blackbox_serialize   = countedref_serialize;
733  bbxshared->blackbox_deserialize = countedref_deserialize;
734
735  bbxshared->blackbox_CheckAssign = countedref_CheckAssign;
736  bbxshared->blackbox_Assign  = countedref_AssignShared;
737  bbxshared->blackbox_destroy = countedref_destroyShared;
738  bbxshared->blackbox_Op1     = countedref_Op1Shared;
739  bbxshared->blackbox_Op2     = countedref_Op2Shared;
740  bbxshared->blackbox_Init    = countedref_InitShared;
741  bbxshared->data             = omAlloc0(newstruct_desc_size());
742  setBlackboxStuff(bbxshared, "shared");
743}
744
745
Note: See TracBrowser for help on using the repository browser.