Back to index

nux  3.0.0
Object.h
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright 2010-2011 Inalogic® Inc.
00004  *
00005  * This program is free software: you can redistribute it and/or modify it
00006  * under the terms of the GNU Lesser General Public License, as
00007  * published by the  Free Software Foundation; either version 2.1 or 3.0
00008  * of the License.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranties of
00012  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00013  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00014  * License for more details.
00015  *
00016  * You should have received a copy of both the GNU Lesser General Public
00017  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00018  *
00019  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00020  *
00021  */
00022 
00023 
00024 #ifndef NUXCORE_OBJECT_H
00025 #define NUXCORE_OBJECT_H
00026 
00027 #include <sigc++/trackable.h>
00028 #include <sigc++/signal.h>
00029 #include "ObjectType.h"
00030 #include "Property.h"
00031 #include "PropertyTraits.h"
00032 
00033 #define NUX_FILE_LINE_PROTO     const char* __Nux_FileName__=__FILE__, int __Nux_LineNumber__ = __LINE__
00034 #define NUX_FILE_LINE_DECL      const char* __Nux_FileName__, int __Nux_LineNumber__
00035 #define NUX_FILE_LINE_PARAM     __Nux_FileName__, __Nux_LineNumber__
00036 #define NUX_TRACKER_LOCATION    __FILE__, __LINE__
00037 
00038 #define OnDestroyed object_destroyed
00039 
00040 
00041 namespace nux
00042 {
00043   template <typename T>
00044   class ObjectPtr;
00045 
00046   template <typename T>
00047   class ObjectWeakPtr;
00048 
00049   class ObjectStats
00050   {
00051     NUX_DECLARE_GLOBAL_OBJECT (ObjectStats, GlobalSingletonInitializer);
00052   public:
00053     typedef std::list<void*> AllocationList;
00054     AllocationList _allocation_list;
00055     int _total_allocated_size;  
00056     int _number_of_objects;     
00057   };
00058 
00059 #define GObjectStats NUX_GLOBAL_OBJECT_INSTANCE(nux::ObjectStats)
00060 
00062 
00066   class Trackable: public nux::Introspectable, public sigc::trackable
00067   {
00068   public:
00069     NUX_DECLARE_ROOT_OBJECT_TYPE (Trackable);
00071     /*
00072         @return True if the object reference is owned.
00073     */
00074     bool OwnsTheReference();
00075 
00077     /*
00078         @return True if the object was allocated dynamically.
00079     */
00080     bool IsHeapAllocated();
00081 
00083     /*
00084         @return True if the object was allocated dynamically.
00085     */
00086     bool IsDynamic() const;
00087 
00088 
00090     /*
00091         Widget are typically created and added to containers. It is decided that when widgets are created, they should have a floating reference
00092         and their reference count is set to 1.
00093         {
00094             Button* button = new Button();  // button ref_cout = 1, floating = true;
00095             container->AddButton(button);   // button has a floating reference; when container call button->ref() the ref count
00096                                             // of button remains at 1 but the floating reference is set to false. From now on,
00097                                             // calling button->ref will always increase the ref count (since button no longer has a floating reference).
00098         }
00099 
00100         It is best to pair calls to ref() with unref() when it comes to widgets. So if a widget was not added to a container and so it still has a
00101         floating reference, then call Dispose(). Dispose does some sanity check; it verifies that:
00102              ref_count == 1
00103              floating == true
00104         If these conditions are verified, dispose will cause the object to be destroyed.
00105         Calling unref() on an object that has a floating reference will trigger a warning/error in order to invite the
00106         developer. The developer can either ref the object first before calling unref or simply not create the widget since it
00107         does not appear to have been used.
00108 
00109         During development it often happen that one forget to dispose an object with a floating reference.
00110         Assuming that all functions that receive a reference counted object properly call ref on the object and that the compiler
00111         can detect unused variables, then the developer should have a way to detect reference counted objects that are not owned.
00112         It is up to the developer to properly handle these objects.
00113 
00114         @return True if the object has been referenced.
00115     */
00116     virtual bool Reference();
00117 
00119 
00122     virtual bool UnReference();
00123 
00125 
00131     virtual bool SinkReference();
00132 
00134 
00137     virtual bool Dispose();
00138 
00140 
00143     virtual int GetObjectSize ();
00144 
00145     static std::new_handler set_new_handler (std::new_handler handler);
00146     static void *operator new (size_t size);
00147 
00148 #if (__GNUC__ < 4 && __GNUC_MINOR__ < 4)
00149     static void *operator new (size_t size, void *ptr);
00150 #endif
00151 
00152     static void operator delete (void *ptr);
00153 
00154   protected:
00155     Trackable();
00156     virtual ~Trackable() = 0;
00157     void SetOwnedReference (bool b);
00158     int _heap_allocated;
00159 
00160   private:
00161     // Trackable objects are not copyable.
00162     Trackable (const Trackable &);
00163     Trackable &operator= (const Trackable &);
00164 
00165     static std::new_handler _new_current_handler;
00166 
00167     bool _owns_the_reference;
00168     int _size_of_this_object;
00169   };
00170 
00172   class Object: public Trackable
00173   {
00174   public:
00175     NUX_DECLARE_OBJECT_TYPE (BaseObject, Trackable);
00176 
00178     Object (bool OwnTheReference = true, NUX_FILE_LINE_PROTO);
00180 
00183     bool Reference();
00184 
00186 
00190     bool UnReference();
00191 
00193 
00199     virtual bool SinkReference();
00200 
00202 
00205     virtual bool Dispose();
00206 
00208 
00211     int GetReferenceCount () const;
00212 
00214     sigc::signal <void, Object *> object_destroyed;
00215 
00216     std::string GetAllocationLoation() const;
00217 
00218   protected:
00220     /*
00221         Private destructor. Ensure that Object cannot be created on the stack
00222         (only on the heap), but objects that inherits from Object can stil be
00223         created on the stack or on the heap.  (MEC++ item27)
00224     */
00225     virtual ~Object();
00226 
00227   private:
00229     void Destroy();
00230 
00231     Object (const Object &);
00232     Object &operator = (const Object &);
00233 
00234     const char* allocation_file_name_;
00235     int allocation_line_number_;
00236 
00237     NThreadSafeCounter* reference_count_;
00239     NThreadSafeCounter* objectptr_count_;
00240 
00241     template <typename T>
00242     friend class ObjectPtr;
00243 
00244     template <typename T>
00245     friend class ObjectWeakPtr;
00246     friend class ObjectStats;
00247   };
00248 
00249 }
00250 
00251 #endif // NUXOBJECT_H
00252