Pointer.h
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:10k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. /*
  2.  *  OpenKore C++ Standard Library
  3.  *  Copyright (C) 2006  VCL
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Lesser General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2.1 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Lesser General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Lesser General Public
  16.  *  License along with this library; if not, write to the Free Software
  17.  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  18.  *  MA  02110-1301  USA
  19.  */
  20. #ifndef _OSL_POINTER_H_
  21. #define _OSL_POINTER_H_
  22. #include <typeinfo>
  23. #include <stdio.h>
  24. #include "Object.h"
  25. #include "Exception.h"
  26. #include "Threading/Atomic.h"
  27. namespace OSL {
  28. /**
  29.  * Thrown when a NULL Pointer class is unable to dereference itself.
  30.  *
  31.  * @class PointerException OSL/Pointer.h
  32.  * @ingroup Base
  33.  */
  34. class PointerException: public Exception {
  35. public:
  36. PointerException(const char *msg = NULL, int code = 0);
  37. };
  38. template <class T> class Pointer;
  39. namespace _Intern {
  40. /**
  41.  * Class which contains metadata about a referee, such as
  42.  * the reference count.
  43.  */
  44. template <class T>
  45. class PointerSharedData {
  46. private:
  47. friend class Pointer<T>;
  48. /**
  49.  * The reference count.
  50.  * @invariant refcount >= 0
  51.  */
  52. int refcount;
  53. /** Whether referee is an OSL::Object */
  54. bool isObject;
  55. /** The referee. */
  56. T *data;
  57. public:
  58. PointerSharedData() {
  59. refcount = 1;
  60. isObject = false;
  61. data = NULL;
  62. }
  63. };
  64. }
  65. /**
  66.  * Thread-safe shared smart pointer.
  67.  *
  68.  * Smart pointers allow you to create multiple references to shared
  69.  * data structures, and can perform automatic memory management.
  70.  * See <a href="http://www.google.com/search?q=C%2B%2B+smart+pointer">Google
  71.  * search results on C++ smart pointers</a> for more information and tutorials.
  72.  *
  73.  * Normal pointers have to be managed manually:
  74.  * @code
  75.  * string *some_function() {
  76.  *     string *foo = new string("hello world");
  77.  *     string *bar = foo;
  78.  *     delete foo;  // bar is now an invalid pointer!
  79.  *     return new string("hello world");
  80.  * }
  81.  *
  82.  * void some_function_2() {
  83.  *     some_function();  // Memory leak!
  84.  * }
  85.  * @endcode
  86.  *
  87.  * With smart pointers, the referenced data only deleted automatically
  88.  * when the last smart pointer is deleted:
  89.  * @code
  90.  * Pointer<string> some_function() {
  91.  *     Pointer<string> bar;
  92.  *     do {
  93.  *         Pointer<string> foo(string("hello world"));
  94.  *         bar = foo;
  95.  *     } while (0);
  96.  *     // foo is now deleted, but its string is not.
  97.  *     // bar is still a valid pointer.
  98.  *     return bar;
  99.  * }
  100.  *
  101.  * void some_function2() {
  102.  *     some_function();
  103.  *     // bar is now automatically deleted. No memory leak!
  104.  * }
  105.  * @endcode
  106.  *
  107.  *
  108.  * @section Usage
  109.  * Smart pointers behave just like normal pointers. Instead of <tt>Foo *</tt>
  110.  * you write <tt>Pointer<Foo></tt>.
  111.  *
  112.  * To create a smart pointer, use the following syntax:
  113.  * @code
  114.  * Pointer<Foo> bar(new Foo());
  115.  * @endcode
  116.  *
  117.  * The following pointer operations are all valid, as smart pointers behave like
  118.  * normal pointers:
  119.  * @code
  120.  * bar->hello();
  121.  * (*bar).hello();
  122.  * Foo *normal_pointer = bar;
  123.  * @endcode
  124.  *
  125.  * If you want to force a smart pointer to dereference its data, set it to NULL:
  126.  * @code
  127.  * Pointer<Foo> bar(new Foo());
  128.  * bar = NULL;   // The Foo instance is now deleted.
  129.  * @endcode
  130.  *
  131.  * If you try to dereference an empty smart pointer, it will throw PointerException&:
  132.  * @code
  133.  * Pointer<Foo> empty;
  134.  * *empty; // PointerException& thrown!
  135.  * @endcode
  136.  *
  137.  * On the other hand, the -> operator will return NULL if the smart pointer
  138.  * is empty:
  139.  * @code
  140.  * Pointer<Foo> empty;
  141.  * empty.operator->();   // NULL
  142.  * (void *) empty;       // NULL
  143.  * empty->test();        // Crash!
  144.  * @endcode
  145.  *
  146.  * @warning
  147.  * Do NOT create an empty smart pointer by passing an empty parameter list to its
  148.  * constructor! The following will not work:
  149.  * @code
  150.  * Pointer<Foo> p();
  151.  * @endcode
  152.  * while the following will:
  153.  * @code
  154.  * Pointer<Foo> p;
  155.  * @endcode
  156.  * This is due to weird C++ caveats.
  157.  *
  158.  *
  159.  * @section object Special support for Object reference counting
  160.  * Since Object provides manual reference counting support, Pointer provides
  161.  * a way to automatically make use of that. Use createForObject() to create
  162.  * a smart pointer to an Object. See createForObject() for more information,
  163.  * examples and caveats.
  164.  *
  165.  *
  166.  * @anchor Pointer-Caveats
  167.  * @section Caveats
  168.  * Don't create two smart pointers to the same data. Newly instantiated
  169.  * smart pointers don't know about other smart pointers that reference
  170.  * the same data. You may only copy existing smart pointers.
  171.  *
  172.  * So the following will result in memory corruption:
  173.  * @code
  174.  * do {
  175.  *     Foo *bar = new Foo();
  176.  *     Pointer<Foo> pointer1 = bar;
  177.  *     do {
  178.  *         Pointer<Foo> pointer2 = bar;
  179.  *         // pointer2 doesn't know pointer1 references bar.
  180.  *     } while (0);
  181.  *     // At this point, pointer2 is deleted, and bar is too.
  182.  *     // pointer1 is now an invalid pointer.
  183.  *     // You should have written this instead: pointer2 = pointer1
  184.  * } while(0);
  185.  * // Memory corruption!
  186.  * @endcode
  187.  *
  188.  * The only exception is when you use smart pointers in combination with
  189.  * Object reference counting. See createForObject() for more information.
  190.  *
  191.  * @class Pointer OSL/Pointer.h
  192.  * @ingroup Base
  193.  */
  194. template <class T>
  195. class Pointer {
  196. private:
  197. _Intern::PointerSharedData<T> *shared;
  198. Pointer(T *data, bool isObject) throw() {
  199. createReference(data, isObject);
  200. }
  201. void
  202. dereferenceCurrent() throw() {
  203. if (shared != NULL && Atomic::decrement(shared->refcount)) {
  204. if (shared->isObject) {
  205. reinterpret_cast<Object *>(shared->data)->unref();
  206. } else {
  207. delete shared->data;
  208. }
  209. delete shared;
  210. }
  211. }
  212. void
  213. createReference(T *data, bool isObject) throw() {
  214. if (data != NULL) {
  215. shared = new _Intern::PointerSharedData<T>();
  216. shared->isObject = isObject;
  217. if (isObject) {
  218. reinterpret_cast<Object *>(data)->ref();
  219. }
  220. shared->data = data;
  221. } else {
  222. shared = NULL;
  223. }
  224. }
  225. void
  226. createReference(const Pointer<T> &pointer) throw() {
  227. shared = pointer.shared;
  228. Atomic::increment(shared->refcount);
  229. }
  230. public:
  231. Pointer() throw() {
  232. createReference(NULL, false);
  233. }
  234. Pointer(T *data) throw() {
  235. createReference(data, false);
  236. }
  237. /**
  238.  * Creates a smart pointer for the given Object. Unlike a normal
  239.  * smart pointer, smart pointers created using this method use
  240.  * the Object's own reference counting support.
  241.  *
  242.  * Each instance of a smart pointer created by this function will
  243.  * increment the Obejct's reference count by 1, and will decrement
  244.  * it by 1 when the smart pointer is deleted. This also means that
  245.  * if the last smart pointer to this Object is deleted, the Object
  246.  * won't be deleted - you have to unreference it one more time.
  247.  *
  248.  * This is best illustrated by an example. Normal smart pointers
  249.  * work like this:
  250.  * @code
  251.  * Object *foo = new Object();
  252.  * foo->ref();
  253.  * // foo now has a reference count of 2.
  254.  * do {
  255.  *     Pointer<Object> p(foo);
  256.  *     // foo still has a reference count of 2.
  257.  * } while (0);
  258.  * // foo is now deleted. The ref() call didn't prevent it from
  259.  * // being deleted since the smart pointer calls 'delete foo'
  260.  * @endcode
  261.  *
  262.  * A smart pointer created with this method works like this:
  263.  * @code
  264.  * Object *foo = new Object();
  265.  * // foo has a reference count of 1.
  266.  * do {
  267.  *     Pointer<Object> p = Pointer<Object>::createForObject(foo);
  268.  *     // foo now has a reference count of 2.
  269.  * } while (0);
  270.  * // p is deleted, so foo now has a reference count of 1.
  271.  * // We unreference it 1 more time to really delete it:
  272.  * foo->unref();
  273.  * @endcode
  274.  *
  275.  * Thus, using this method also gives you the advantage of being able
  276.  * to create multiple Pointer instances for Object objects without
  277.  * problems (as documented by the @ref Pointer-Caveats "Caveats"
  278.  * section).
  279.  *
  280.  * @section Caveats
  281.  * There is only one caveat. The = operator doesn't know whether it's
  282.  * been assigned an Object (due to limitations in C++).
  283.  * For example:
  284.  * @code
  285.  * Object *foo = new Object();
  286.  * do {
  287.  *     Pointer<Object> p;
  288.  *     p = foo; // <----------
  289.  * } while (0);
  290.  * // p doesn't know that foo is an Object. So it won't increase
  291.  * // p's reference count. Therefore, foo is now deleted.
  292.  * @endcode
  293.  */
  294. static Pointer<T>
  295. createForObject(Object *data) throw() {
  296. return Pointer<T>(static_cast<T *>(data), true);
  297. }
  298. Pointer(const Pointer<T> &pointer) throw() {
  299. createReference(pointer);
  300. }
  301. virtual ~Pointer() throw() {
  302. dereferenceCurrent();
  303. }
  304. Pointer<T> &
  305. operator=(T *data) throw() {
  306. if (shared == NULL || data != shared->data) {
  307. dereferenceCurrent();
  308. createReference(data, false);
  309. }
  310. return *this;
  311. }
  312. Pointer<T> &
  313. operator=(const Pointer<T> &pointer) throw() {
  314. if (shared == NULL || pointer.shared->data != shared->data) {
  315. dereferenceCurrent();
  316. createReference(pointer);
  317. }
  318. return *this;
  319. }
  320. T& operator*() throw(PointerException) {
  321. if (shared != NULL && shared->data != NULL) {
  322. return *shared->data;
  323. } else {
  324. throw PointerException("Cannot dereference a NULL Pointer.");
  325. }
  326. }
  327. T* operator->() throw() {
  328. if (shared != NULL) {
  329. return shared->data;
  330. } else {
  331. return NULL;
  332. }
  333. }
  334. operator T * () throw() {
  335. if (shared != NULL) {
  336. return shared->data;
  337. } else {
  338. return NULL;
  339. }
  340. }
  341. operator T & () throw(PointerException) {
  342. if (shared != NULL) {
  343. return *shared->data;
  344. } else {
  345. throw PointerException("Cannot dereference a NULL Pointer.");
  346. }
  347. }
  348. };
  349. }
  350. #endif /* _OSL_POINTER_H_ */