source: git/Singular/countedref.cc @ 8d1432e

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