1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef _MORKHANDLE_
7 #define _MORKHANDLE_ 1
8 
9 #ifndef _MORK_
10 #  include "mork.h"
11 #endif
12 
13 #ifndef _MORKNODE_
14 #  include "morkNode.h"
15 #endif
16 
17 #ifndef _MORKDEQUE_
18 #  include "morkDeque.h"
19 #endif
20 
21 #ifndef _MORKPOOL_
22 #  include "morkPool.h"
23 #endif
24 
25 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
26 
27 class morkPool;
28 class morkObject;
29 class morkFactory;
30 
31 #define morkDerived_kHandle /*i*/ 0x486E /* ascii 'Hn' */
32 #define morkHandle_kTag 0x68416E44       /* ascii 'hAnD' */
33 
34 /*| morkHandle:
35 |*/
36 class morkHandle : public morkNode {
37   // public: // slots inherited from morkNode (meant to inform only)
38   // nsIMdbHeap*    mNode_Heap;
39 
40   // mork_base      mNode_Base;     // must equal morkBase_kNode
41   // mork_derived   mNode_Derived;  // depends on specific node subclass
42 
43   // mork_access    mNode_Access;   // kOpen, kClosing, kShut, or kDead
44   // mork_usage     mNode_Usage;    // kHeap, kStack, kMember, kGlobal, kNone
45   // mork_able      mNode_Mutable;  // can this node be modified?
46   // mork_load      mNode_Load;     // is this node clean or dirty?
47 
48   // mork_uses      mNode_Uses;     // refcount for strong refs
49   // mork_refs      mNode_Refs;     // refcount for strong refs + weak refs
50 
51  public:  // state is public because the entire Mork system is private
52   mork_u4 mHandle_Tag;           // must equal morkHandle_kTag
53   morkEnv* mHandle_Env;          // pool that allocated this handle
54   morkHandleFace* mHandle_Face;  // cookie from pool containing this
55   morkObject* mHandle_Object;    // object this handle wraps for MDB API
56   mork_magic mHandle_Magic;      // magic sig different in each subclass
57 
58   // { ===== begin morkNode interface =====
59  public:  // morkNode virtual methods
60   virtual void CloseMorkNode(
61       morkEnv* ev) override;  // CloseHandle() only if open
62   virtual ~morkHandle();      // assert that CloseHandle() executed earlier
63 
64  public:  // morkHandle construction & destruction
65   morkHandle(
66       morkEnv* ev,                // note morkUsage is always morkUsage_kPool
67       morkHandleFace* ioFace,     // must not be nil, cookie for this handle
68       morkObject* ioObject,       // must not be nil, the object for this handle
69       mork_magic inMagic);        // magic sig to denote specific subclass
70   void CloseHandle(morkEnv* ev);  // called by CloseMorkNode();
71 
72  private:  // copying is not allowed
73   morkHandle(const morkHandle& other);
74   morkHandle& operator=(const morkHandle& other);
75 
76  protected:  // special case empty construction for morkHandleFrame
77   friend class morkHandleFrame;
morkHandle()78   morkHandle() {}
79 
80  public:  // dynamic type identification
IsHandle()81   mork_bool IsHandle() const {
82     return IsNode() && mNode_Derived == morkDerived_kHandle;
83   }
84   // } ===== end morkNode methods =====
85 
86  public:  // morkHandle memory management operators
new(size_t inSize,morkPool & ioPool,morkZone & ioZone,morkEnv * ev)87   void* operator new(size_t inSize, morkPool& ioPool, morkZone& ioZone,
88                      morkEnv* ev) noexcept(true) {
89     return ioPool.NewHandle(ev, inSize, &ioZone);
90   }
91 
new(size_t inSize,morkPool & ioPool,morkEnv * ev)92   void* operator new(size_t inSize, morkPool& ioPool,
93                      morkEnv* ev) noexcept(true) {
94     return ioPool.NewHandle(ev, inSize, (morkZone*)0);
95   }
96 
new(size_t inSize,morkHandleFace * ioFace)97   void* operator new(size_t inSize, morkHandleFace* ioFace) noexcept(true) {
98     MORK_USED_1(inSize);
99     return ioFace;
100   }
101 
102  public:  // other handle methods
GoodHandleTag()103   mork_bool GoodHandleTag() const { return mHandle_Tag == morkHandle_kTag; }
104 
105   void NewBadMagicHandleError(morkEnv* ev, mork_magic inMagic) const;
106   void NewDownHandleError(morkEnv* ev) const;
107   void NilFactoryError(morkEnv* ev) const;
108   void NilHandleObjectError(morkEnv* ev) const;
109   void NonNodeObjectError(morkEnv* ev) const;
110   void NonOpenObjectError(morkEnv* ev) const;
111 
112   morkObject* GetGoodHandleObject(morkEnv* ev, mork_bool inMutable,
113                                   mork_magic inMagicType,
114                                   mork_bool inClosedOkay) const;
115 
116  public:  // interface supporting mdbObject methods
117   morkEnv* CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable,
118                         mork_bool inClosedOkay, nsresult* outErr) const;
119 
120   // { ----- begin mdbObject style methods -----
121   nsresult Handle_IsFrozenMdbObject(nsIMdbEnv* ev, mdb_bool* outIsReadonly);
122 
123   nsresult Handle_GetMdbFactory(nsIMdbEnv* ev, nsIMdbFactory** acqFactory);
124   nsresult Handle_GetWeakRefCount(nsIMdbEnv* ev, mdb_count* outCount);
125   nsresult Handle_GetStrongRefCount(nsIMdbEnv* ev, mdb_count* outCount);
126 
127   nsresult Handle_AddWeakRef(nsIMdbEnv* ev);
128   nsresult Handle_AddStrongRef(nsIMdbEnv* ev);
129 
130   nsresult Handle_CutWeakRef(nsIMdbEnv* ev);
131   nsresult Handle_CutStrongRef(nsIMdbEnv* ev);
132 
133   nsresult Handle_CloseMdbObject(nsIMdbEnv* ev);
134   nsresult Handle_IsOpenMdbObject(nsIMdbEnv* ev, mdb_bool* outOpen);
135   // } ----- end mdbObject style methods -----
136 
137  public:  // typesafe refcounting inlines calling inherited morkNode methods
SlotWeakHandle(morkHandle * me,morkEnv * ev,morkHandle ** ioSlot)138   static void SlotWeakHandle(morkHandle* me, morkEnv* ev, morkHandle** ioSlot) {
139     morkNode::SlotWeakNode((morkNode*)me, ev, (morkNode**)ioSlot);
140   }
141 
SlotStrongHandle(morkHandle * me,morkEnv * ev,morkHandle ** ioSlot)142   static void SlotStrongHandle(morkHandle* me, morkEnv* ev,
143                                morkHandle** ioSlot) {
144     morkNode::SlotStrongNode((morkNode*)me, ev, (morkNode**)ioSlot);
145   }
146 };
147 
148 #define morkHandleFrame_kPadSlotCount 4
149 
150 /*| morkHandleFrame: an object format used for allocating and maintaining
151 **| instances of morkHandle, with leading slots used to maintain this in a
152 **| linked list, and following slots to provide extra footprint that might
153 **| be needed by any morkHandle subclasses that include very little extra
154 **| space (by virtue of the fact that each morkHandle subclass is expected
155 **| to multiply inherit from another base class that has only abstract methods
156 **| for space overhead related only to some vtable representation).
157 |*/
158 class morkHandleFrame {
159  public:
160   morkLink mHandleFrame_Link;  // list storage without trampling Handle
161   morkHandle mHandleFrame_Handle;
162   mork_ip mHandleFrame_Padding[morkHandleFrame_kPadSlotCount];
163 
164  public:
AsHandle()165   morkHandle* AsHandle() { return &mHandleFrame_Handle; }
166 
morkHandleFrame()167   morkHandleFrame() {}  // actually, morkHandleFrame never gets constructed
168 
169  private:  // copying is not allowed
170   morkHandleFrame(const morkHandleFrame& other);
171   morkHandleFrame& operator=(const morkHandleFrame& other);
172 };
173 
174 #define morkHandleFrame_kHandleOffset \
175   mork_OffsetOf(morkHandleFrame, mHandleFrame_Handle)
176 
177 #define morkHandle_AsHandleFrame(h) \
178   ((h)->mHandle_Block,              \
179    ((morkHandleFrame*)(((mork_u1*)(h)) - morkHandleFrame_kHandleOffset)))
180 
181 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
182 
183 #endif /* _MORKHANDLE_ */
184