InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
InterfacePtr.h
1 //========================================================================================
2 //
3 // $File$
4 //
5 // Owner: Zak Williamson and Mat Marcus
6 //
7 // $Author$
8 //
9 // $DateTime$
10 //
11 // $Revision$
12 //
13 // $Change$
14 //
15 // Copyright 1997-2010 Adobe Systems Incorporated. All rights reserved.
16 //
17 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
18 // with the terms of the Adobe license agreement accompanying it. If you have received
19 // this file from a source other than Adobe, then your use, modification, or
20 // distribution of it requires the prior written permission of Adobe.
21 //
22 //
23 // depot/branches/cw8/source/public/Includes/InterfacePtr.h#1 - branch change 154605 (ktext)
24 //
25 // Provides a template class that acts like a pointer to an interface
26 // but adds the funcationality of automatically calling QueryInterface
27 // and Release as needed.
28 //
29 // The following is a simple smart pointer implementation
30 // that automates the mundane QueryInterface, use, Release pattern.
31 // For example, code like the following:
32 //
33 // IShape * shape = pmInterfacePtr->QueryInterface(IID_ISHAPE);
34 // ASSERT_MSG(shape != nil, "shape is nil!");
35 // shape->Draw();
36 // shape->Release();
37 //
38 // becomes:
39 //
40 // InterfacePtr<IShape> shape(pmInterfacePtr, UseDefaultIID());
41 // shape->Paint();
42 //
43 // OR:
44 //
45 // InterfacePtr<IShape> shape(pmInterfacePtr, IID_ISHAPE);
46 // shape->Paint();
47 //
48 // If only const members will be called then use:
49 //
50 // InterfacePtr<const IShape> shape(pmInterfacePtr, UseDefaultIID());
51 // shape->Paint();
52 //
53 // More importantly, releasing interfaces is automatic (via the
54 // InterfacePtr destructor). There's no need to check all the return's
55 // in a method to be sure they call Release and we'll be better prepared
56 // for backing out via exception handling.
57 //
58 // The constructor performs the QueryInterface, the indirection
59 // operator performs the Assert, and the destructor performs the Release.
60 // Assignment of InterfacePtrs is also possible -- see notes below.
61 //
62 // Caveats
63 // You can use an InterfacePtr in place of the corresponding "real" pointer
64 // in a function call. The implicit conversion operator will see that the
65 // real" pointer is passed.
66 //
67 //========================================================================================
68 
69 #ifndef __InterfacePtr__
70 #define __InterfacePtr__
71 
72 #include "IPMUnknown.h"
73 #include "OMTypes.h" // for PMIID
74 
75 #include "IDataBase.h"
76 #include "UIDRef.h"
77 
78 // -------------------------------------------------------------
79 // Class UseDefaultIID
80 // -------------------------------------------------------------
81 
82 // Passing one of the InterfacePtr constructors an anonymous UseDefaultIID()
83 // as the trailing parameter (instead of a PMIID) causes a special constructor
84 // to be called. This special constructor assumes that the interface IFace
85 // has defined a default ID with the name kDefaultIID. If such an ID has not
86 // been defined then the compiler will complain. A good way to satisfy the
87 // compiler is to then add the definition to the offending Interface. Or
88 // one could just use the "old style" call to InterfacePtr.
89 
90 /****** EXAMPLE *****
91 
92 * ----------
93 * IMyInterface.h:
94 *
95 * #include "xxxID.h"
96 *
97 * class IMyInterface : public IPMUnknown
98 * {
99 * public:
100 * enum { kDefaultIID = kMyInterfaceID};
101 * ...
102 * };
103 *
104 * ----------
105 * Some Client of IMyInterface:
106 *
107 * ...
108 * InterfacePtr<IMyInterface> myInterface(foo, UseDefaultIID());
109 *
110 ******* END EXAMPLE *****/
111 
115 // This is a dummy tag class. It is used only to drive the type system.
116 };
117 
118 // -------------------------------------------------------------
119 // Class InterfacePtr
120 // -------------------------------------------------------------
121 
125 template <class IFace>
127 public:
128 
131  typedef object_type data_type; // Allows containment of InterfacePtr in K2Vector.
132 
133 // -------------------------------------------------------------
134 // Build from a dumb pointer
135 // -------------------------------------------------------------
136 
137 
148  explicit InterfacePtr(IFace* p)
149  : fFace(p)
150 #ifdef ID_ENABLE_DEBUGGING
151  , fDebugLastIIDQueried(kInvalidInterfaceID), fDebugLastBossQueried(kInvalidClass)
152 #endif
153  {
154  (void)
155  static_cast<const IPMUnknown*>(p);
156  }
157 
158 
165  : fFace(QueryInterface_(p, iid))
166  {
167 #ifdef ID_ENABLE_DEBUGGING
168  if(!fFace)
169  SaveOffDebugInfo(p,iid);
170 #endif
171  }
172 
173 
179  : fFace(QueryInterface_(p, IFace::kDefaultIID))
180  {
181 #ifdef ID_ENABLE_DEBUGGING
182  if(!fFace)
183  SaveOffDebugInfo(p,IFace::kDefaultIID);
184 #endif
185  }
186 
190  : fFace(nil)
191 #ifdef ID_ENABLE_DEBUGGING
192  , fDebugLastIIDQueried(kInvalidInterfaceID), fDebugLastBossQueried(kInvalidClass)
193 #endif
194  {}
195 
196 private:
197  // $$$ Could implement operator= in a way that generates a better error message at compile time
198 
201  template <class OtherType>
202  InterfacePtr<IFace>& operator=(OtherType* p); // intentionally unimplemented
203 
204 public:
205 
206 // -------------------------------------------------------------
207 // Build from a smart pointer
208 // -------------------------------------------------------------
209 
210  // These single argument constructors will call AddRef on p.
211  // Release will be called in the destructor.
212 
213 
216  template <class OtherType>
218  :fFace(AddRef_(p.get()))
219 #ifdef ID_ENABLE_DEBUGGING
220  , fDebugLastIIDQueried(p.fDebugLastIIDQueried), fDebugLastBossQueried(p.fDebugLastBossQueried)
221 #endif
222  { /* Implementation Note: we use a template member fucntion here to do the right thing
223  when an InterfacePtr<const IFoo> is constructed from an InterfacePtr<IFoo> */
224  }
225 
231  :fFace(AddRef_(p.get()))
232 #ifdef ID_ENABLE_DEBUGGING
233  , fDebugLastIIDQueried(p.fDebugLastIIDQueried),fDebugLastBossQueried(p.fDebugLastBossQueried)
234 #endif
235  { }
236 
237  InterfacePtr(InterfacePtr<IFace>&& p) noexcept
238  :fFace(p.fFace)
239 #ifdef ID_ENABLE_DEBUGGING
240  , fDebugLastIIDQueried(p.fDebugLastIIDQueried), fDebugLastBossQueried(p.fDebugLastBossQueried)
241 #endif
242  {
243  p.fFace = nil;
244  }
245 
250  template <class OtherType>
252  {
253  // Take ownership of p
254  reset(AddRef_(p.get()));
255 #ifdef ID_ENABLE_DEBUGGING
256  fDebugLastIIDQueried = p.fDebugLastIIDQueried;
257  fDebugLastBossQueried = p.fDebugLastBossQueried;
258 #endif
259  return *this;
260  /* Implementation Note: we use a template member function here to do the right thing
261  when an InterfacePtr<const IFoo> is constructed from an InterfacePtr<IFoo> */
262  }
263 
269  {
270  // Take ownership of p
271  reset(AddRef_(p.get()));
272 #ifdef ID_ENABLE_DEBUGGING
273  fDebugLastIIDQueried = p.fDebugLastIIDQueried;
274  fDebugLastBossQueried = p.fDebugLastBossQueried;
275 #endif
276  return *this;
277  }
278 
279  InterfacePtr<IFace>& operator=(InterfacePtr<IFace>&& p) noexcept
280  {
281  this->swap(p);
282  return *this;
283  }
284 
285 
286 // -------------------------------------------------------------
287 // Build from a database
288 // -------------------------------------------------------------
289  // use these constructors to instantiate from a database
290 
297  : fFace(Instantiate_(db, uid, iid))
298  {
299 #ifdef ID_ENABLE_DEBUGGING
300  if(!fFace)
301  {
302  fDebugLastIIDQueried = iid;
303  if(db)
304  fDebugLastBossQueried = db->GetClass(uid);
305  else
306  fDebugLastBossQueried = kInvalidClass;
307  }
308 #endif
309  }
310 
317  : fFace(Instantiate_(db, uid, IFace::kDefaultIID))
318  {
319 #ifdef ID_ENABLE_DEBUGGING
320  if(!fFace)
321  {
322  fDebugLastIIDQueried = IFace::kDefaultIID;
323  if(db)
324  fDebugLastBossQueried = db->GetClass(uid);
325  else
326  fDebugLastBossQueried = kInvalidClass;
327  }
328 #endif
329  }
330 
335  InterfacePtr(const UIDRef& ref, PMIID iid)
336  : fFace(Instantiate_(ref, iid))
337  {
338 #ifdef ID_ENABLE_DEBUGGING
339  if(!fFace)
340  {
341  fDebugLastIIDQueried = iid;
342  if(ref.GetDataBase())
343  fDebugLastBossQueried = ref.GetDataBase()->GetClass(ref.GetUID());
344  else
345  fDebugLastBossQueried = kInvalidClass;
346  }
347 #endif
348  }
349 
355  InterfacePtr(const UIDRef& ref, const UseDefaultIID&)
356  : fFace(Instantiate_(ref, IFace::kDefaultIID))
357  {
358 #ifdef ID_ENABLE_DEBUGGING
359  if(!fFace)
360  {
361  fDebugLastIIDQueried = IFace::kDefaultIID;
362  if(ref.GetDataBase())
363  fDebugLastBossQueried = ref.GetDataBase()->GetClass(ref.GetUID());
364  else
365  fDebugLastBossQueried = kInvalidClass;
366  }
367 #endif
368  }
369 
370 // -------------------------------------------------------------
371 // Destroy
372 // -------------------------------------------------------------
373  ~InterfacePtr();
374 
375 // -------------------------------------------------------------
376 // Use the pointer
377 // -------------------------------------------------------------
381  operator IFace*() const { return fFace; }
382  // We allow the cast operator to return a nil pointer
383  // since it is valid to test against nil and may be valid
384  // to pass a nil pointer to some methods.
385 
390  IFace * operator ->() const
391  {
392  #ifdef ID_ENABLE_DEBUGGING
393  if(!fFace)
394  AssertAboutUsingNilPtr();
395  #endif
396  return fFace;
397  }
398 
402  bool16 operator!() const { return fFace == nil; }
403 
409  IFace* forget() // was release
410  {
411  IFace* result = fFace;
412  fFace = 0;
413 #ifdef ID_ENABLE_DEBUGGING
414  fDebugLastIIDQueried = kInvalidInterfaceID;
415  fDebugLastBossQueried = kInvalidClass;
416 #endif
417  return result;
418  }
419 
423  IFace* get() const { return fFace; }
424 
429  void reset(IFace* p = 0)
430  {
431  IFace* oldFace = fFace;
432  fFace = p;
433 #ifdef ID_ENABLE_DEBUGGING
434  fDebugLastIIDQueried = kInvalidInterfaceID;
435  fDebugLastBossQueried = kInvalidClass;
436 #endif
437  Release_(oldFace);
438  }
439 
440  void swap(InterfacePtr<IFace>& other) noexcept
441  {
442  using std::swap;
443  swap(fFace, other.fFace);
444 #ifdef ID_ENABLE_DEBUGGING
445  swap(fDebugLastBossQueried, other.fDebugLastBossQueried);
446  swap(fDebugLastIIDQueried, other.fDebugLastIIDQueried);
447 #endif
448  }
449 
450 private:
451 
452  template <class T>
453  static IFace* AddRef_(const T* p) { if(p) p->AddRef(); return static_cast<IFace*>(const_cast<T*>(p));}
454 
455  static void Release_(IFace* p)
456  { if(p) p->Release(); }
457 
458  static IFace* QueryInterface_(const IPMUnknown* p, PMIID id)
459  { return p? static_cast<IFace*>(p->QueryInterface(id)) : nil; }
460 
461  static IFace* Instantiate_(IDataBase* db, UID uid, PMIID iid)
462  { return db ? static_cast<IFace*>(db->Instantiate(uid, iid)) : nil; }
463 
464  static IFace* Instantiate_(const UIDRef& ref, PMIID iid)
465  { IDataBase* db = ref.GetDataBase(); return db ? static_cast<IFace*>(db->Instantiate(ref.GetUID(), iid)) : nil; }
466 
467 #ifdef ID_ENABLE_DEBUGGING
468  void AssertAboutUsingNilPtr() const;
469  void SaveOffDebugInfo(const IPMUnknown* p, PMIID iid);
470 #endif
471 
472 #ifdef ID_ENABLE_DEBUGGING
473  public: // ick - this has to be public so I can use it for the IntefacePtrs containing <OtherType>
474  ClassID fDebugLastBossQueried;
475  PMIID fDebugLastIIDQueried;
476  private:
477 #endif
478  IFace * fFace;
479 };
480 
481 template <class T>
482 inline void swap(InterfacePtr<T> &a, InterfacePtr<T> &b) noexcept
483 {
484  a.swap(b);
485 }
486 
487 #ifdef ID_ENABLE_DEBUGGING
488 #include "IControllingUnknown.h"
489 
490 template <class T> void InterfacePtr<T>::SaveOffDebugInfo(const IPMUnknown* p, PMIID iid)
491 {
492  fDebugLastIIDQueried = iid;
493  fDebugLastBossQueried = kInvalidClass;
494  if(p)
495  {
496  IControllingUnknown *boss = (IControllingUnknown*)p->QueryInterface(IID_ICONTROLLINGUNKNOWN);
497  if(boss)
498  {
499  fDebugLastBossQueried = boss->GetClass();
500  boss->Release();
501  }
502 
503  }
504 }
505 
506 #include "DebugClassUtils.h"
507 template <class T> void InterfacePtr<T>::AssertAboutUsingNilPtr() const
508 {
509  DebugClassUtilsBuffer idBuf1,idBuf2;
510  ASSERT_FAIL(FORMAT_ARGS("About to use nil interface ptr! Queried IID was %s, on Boss %s",DebugClassUtils::GetIDName(&idBuf1,fDebugLastIIDQueried),DebugClassUtils::GetIDName(&idBuf2,fDebugLastBossQueried)));
511 }
512 #endif
513 
514 
515 //#if MACINTOSH
516 #if 0
517 void DestroyInterfacePtr(); // shouldn't be cross toc
518 
519 template <class T>
521  {
522  nofralloc
523  b DestroyInterfacePtr
524 }
525 #else
526 
527 template <class T>
529 {
530  Release_(fFace);
531 }
532 #endif // MACINTOSH
533 
534 // specialize adobe::type_info<> to avoid typeid problems across DLL boundaries
535 ADOBE_NAME_TYPE_1("interfaceptr:indesign:adobe",InterfacePtr<T0>)
536 
537 #endif // __InterfacePtr__
538