_ODBMS Object Management_
by Chris Aakre 


Example 1:

Link<Solution> solution = myapp.FindSolution("1234");
cout << solution->GetTitle();



Listing One
class RefAny
{
};
template <class T>
class Ref : public RefAny
{
public:
 Ref() : referent_(NULL) {}
 Ref(T& obj) : referent_(NULL) { Set(obj); }
 Ref(Ref<T>& ref) : referent_(ref.referent_) {
    if (referent_) referent_->AddRef(*this); }
    ~Ref() { Clear();
 }
 T& operator ()() const { return Deref(); }
 T& operator =(T& obj) { Clear(); return Set(obj); }

 void Clear () { if (referent_) referent->RemoveRef(*this); }

private:
 T& Deref () const {
 if (!referent_) {
    NullRefException err(__FILE__,__LINE__);
    throw err;
 }
 return *referent_;
 }

 T& Set (T& obj) {
    referent_ = &obj;
    obj.AddRef(*this);
    return obj;
 }
private:
 T* referent_;
};
class Refable
{
public:
 void AddRef(RefAny& ref) { refs_.Insert(&ref); }
 void RemoveRef(RefAny& ref) {
    refs_.Delete(&ref);
    if (refs_.Length() == 0) SignalZeroRefs();
 }
 virtual void SignalZeroRefs() { delete this; }

private:
 Set<RefAny*> refs_;
};


Listing Two
class Solution : public Refable
{
   Solution (char* id, char* title) : id_(id), title_(title) {}

   char* GetTitle() const { return title_; }
   char* GetID() const { return id_; } 

private:
   char* title_;
   char* id_;
}
Ref<Solution> App::CreateSolution(char* title)
{
   Ref<Solution> solution = new Solution(title);
   return solution;
}
void main()
{
   App app;
   Ref<Solution> solution = app.CreateSolution("1234");
   cout << "Created solution " << solution().GetTitle();
}


Listing Three 
template <class T>
class RLink
{
public:
  RLink() : link_() {}
  RLink(const Link<T>& link) : theLink(link) {}

  Ref<T> MakeRef (o_lockmode lm) const {
    Ref<T> ref;
    if (!link_.in_cache() ||
    (GetLock() == NOLOCK && lm != NOLOCK) ) {
      ref = ::dom->refreshobj(link_,lm);
    } else {
      ref = *link_;
    }
    return ref;
  }
  o_lockmode GetLock () {
    o_lockmode  current_lock = NOLOCK;
    o_u4b       lock_counter = 0;
    link_.getcachedlockinfo(NULL, &current_lock, &lock_counter);
    return current_lock;
  }
private:
  Link<T> link_;
};

class Object : public PObject, public Refable
{
public:
  void SignalZeroRefs() {
    DowngradeLock(NOLOCK);
    Unpin();
  }
  void Dirty() {
    Link<Object> link(this);
    if (link.GetLock() == NOLOCK) {
      DirtyWithoutLockException err(__FILE__,__FILE__);
      throw err;
    }
  }
private:
  void Unpin () {
    Link<Object> link(this);
    while (link.is_pinned()) {
      link.unpinobj();
    }
  }
  void DowngradeLock (o_lockmode lm) {
    Link<Object> link(this);
    ::dom->downgradelock(link,lm);
  }
  void dirty() { PObject::dirty(); }
};


Listing Four
class PSolution : public Object
{
   PSolution (char* id, char* title) : id_(id), title_(title) {}

   char* GetTitle() const { return title_; }
   char* GetID() const { return id_; } 

private:
   PString title_;
   PString id_;
}
Ref<PSolution> App::CreateSolution(char* id, char* title)
{
   // Create persistent solution object using overloaded new operator macro.
   Ref<PSolution> solution = O_NEW_PERSISTENT(PSolution)(id,title);
   return solution;
}
void main()
{
   App app;
   Ref<PSolution> solution = app.CreateSolution("1234","My Solution");
   cout << "Created persistent solution " << solution().GetID()
        << " - " << solution().GetTitle() << endl;
}


Listing Five
void SetTitle (RLink<PSolution>& link, char* title)
{
   // Caches C++ pointer to PSolution object
   Ref ref1 = link.MakeRef(NOLOCK);
   char* old_title = ref1().GetTitle();

   if (strcmp(old_title,title) != 0) {
      // May cause object to move!
      Ref ref2 = link.MakeRef(WLOCK);
      ref2().SetTitle(title);
   }
   // Possible error dereferencing ref1!
   cout << "Changed title of solution ID: " << ref1().GetSolutionID() << endl;
}

Listing Six
template <class T>
class PRef : public RefAny
{
public:
  PRef() : referent_(NULL) {}
  PRef(T& obj) : referent_(NULL) { Set(obj); }
  PRef(Ref<T>& ref) : referent_(ref.referent_) {
     if (!referent_.is_null()) Deref().AddRef(*this);
  }
  ~Ref() { Clear(); }

  T& operator ()() const { return Deref(); }
  T& operator =(T& obj) { Clear(); return Set(obj); }

  void Clear () { if (referent_) referent->RemoveRef(*this); }

private:
  T& Deref () const {
    if (referent_.is_null()) {
      NullRefException err(__FILE__,__LINE__);
      throw err;
    }
    return *referent_;
  }
  T& Set (T& obj) {
    Link<T> link(&obj);
    referent_ = link;
    obj.AddRef(*this);
    return obj;
  }
private:
  Link<T> referent_;
};


