Applied ref-couting patch.

Completely reorganized code (more readable to me).
  Minor other changes.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41519 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
2006-09-30 11:20:14 +00:00
parent 21e3246c42
commit 2562c82329
3 changed files with 1822 additions and 1831 deletions

View File

@@ -15,7 +15,18 @@ The {\bf wxVariant} class represents a container for any type.
A variant's value can be changed at run time, possibly to a different type of value. A variant's value can be changed at run time, possibly to a different type of value.
As standard, wxVariant can store values of type bool, char, double, long, string, As standard, wxVariant can store values of type bool, char, double, long, string,
string list, time, date, void pointer, list of strings, and list of variants. However, an application can extend wxVariant's capabilities by deriving from the class \helpref{wxVariantData}{wxvariantdata} and using the wxVariantData form of the wxVariant constructor or assignment operator to assign this data to a variant. Actual values for user-defined types will need to be accessed via the wxVariantData object, unlike the case for basic data types where convenience functions such as GetLong can be used. string list, time, date, void pointer, list of strings, and list of variants.
However, an application can extend wxVariant's capabilities by deriving from the
class \helpref{wxVariantData}{wxvariantdata} and using the wxVariantData form of
the wxVariant constructor or assignment operator to assign this data to a variant.
Actual values for user-defined types will need to be accessed via the wxVariantData
object, unlike the case for basic data types where convenience functions such as
\helpref{GetLong}{wxvariantgetlong} can be used.
Pointers to any \helpref{wxObject}{helpref} derived class can also easily be stored
in a wxVariant. wxVariant will then use wxWidgets' built-in RTTI system to set the
type name (returned by \helpref{GetType}{wxvariantgettype}) and to perform
type-safety checks at runtime.
This class is useful for reducing the programming for certain tasks, such as an editor This class is useful for reducing the programming for certain tasks, such as an editor
for different data types, or a remote procedure call protocol. for different data types, or a remote procedure call protocol.
@@ -23,6 +34,8 @@ for different data types, or a remote procedure call protocol.
An optional name member is associated with a wxVariant. This might be used, for example, in CORBA An optional name member is associated with a wxVariant. This might be used, for example, in CORBA
or OLE automation classes, where named parameters are required. or OLE automation classes, where named parameters are required.
Note that as of wxWidgets 2.7.1, wxVariant is reference counted.
\wxheading{Derived from} \wxheading{Derived from}
\helpref{wxObject}{wxobject} \helpref{wxObject}{wxobject}
@@ -114,6 +127,9 @@ Construction from a odbc timestamp value. Represented internally by a \helpref{
Destructor. Destructor.
Note that destructor is protected, so wxVariantData cannot usually
be deleted. Instead, \helpref{DecRef}{wxvariantdatadecref} should be called.
\membersection{wxVariant::Append}\label{wxvariantappend} \membersection{wxVariant::Append}\label{wxvariantappend}
@@ -121,6 +137,13 @@ Destructor.
Appends a value to the list. Appends a value to the list.
\membersection{wxVariant::Clear}\label{wxvariantclear}
\func{void}{Clear}{\void}
Makes the variant null by deleting the internal data and
set the name to {\it wxEmptyString}.
\membersection{wxVariant::ClearList}\label{wxvariantclearlist} \membersection{wxVariant::ClearList}\label{wxvariantclearlist}
\func{void}{ClearList}{\void} \func{void}{ClearList}{\void}
@@ -179,7 +202,10 @@ Returns the character value.
\constfunc{wxVariantData*}{GetData}{\void} \constfunc{wxVariantData*}{GetData}{\void}
Returns a pointer to the internal variant data. Returns a pointer to the internal variant data. To take ownership
of this data, you must call its \helpref{IncRef}{wxvariantdataincref}
method. When you stop using it, \helpref{DecRef}{wxvariantdatadecref}
must be likewise called.
\membersection{wxVariant::GetDateTime}\label{wxvariantgetdatetime} \membersection{wxVariant::GetDateTime}\label{wxvariantgetdatetime}
@@ -428,6 +454,15 @@ Operator for implicit conversion to a pointer to a \helpref{wxDateTime}{wxdateti
The {\bf wxVariantData} is used to implement a new type for wxVariant. Derive from wxVariantData, The {\bf wxVariantData} is used to implement a new type for wxVariant. Derive from wxVariantData,
and override the pure virtual functions. and override the pure virtual functions.
wxVariantData is reference counted, but you don't normally have to care about this, as
wxVariant manages the count automatically. However, incase your application needs to take
ownership of wxVariantData, be aware that the object is created with reference count of 1,
and passing it to wxVariant will not increase this. In other words, \helpref{IncRef}{wxvariantdataincref}
needs to be called only if you both take ownership of wxVariantData and pass it to a wxVariant.
Also note that the destructor is protected, so you can never explicitly delete a wxVariantData
instance. Instead, \helpref{DecRef}{wxvariantdatadecref} will delete the object automatically
when the reference count reaches zero.
\wxheading{Derived from} \wxheading{Derived from}
\helpref{wxObject}{wxobject} \helpref{wxObject}{wxobject}
@@ -448,11 +483,15 @@ and override the pure virtual functions.
Default constructor. Default constructor.
\membersection{wxVariantData::Copy}\label{wxvariantdatacopy} \membersection{wxVariantData::DecRef}\label{wxvariantdatadecref}
\func{void}{Copy}{\param{wxVariantData\&}{ data}} \func{void}{DecRef}{\void}
Copy the data from `this' object to {\it data}. Decreases reference count. If the count reaches zero, the object is
automatically deleted.
Note that destructor of wxVariantData is protected, so delete
cannot be used as normal. Instead, DecRef should be called.
\membersection{wxVariantData::Eq}\label{wxvariantdataeq} \membersection{wxVariantData::Eq}\label{wxvariantdataeq}
@@ -473,6 +512,12 @@ Returns the string type of the data.
If the data is a wxObject returns a pointer to the objects wxClassInfo structure, if If the data is a wxObject returns a pointer to the objects wxClassInfo structure, if
the data isn't a wxObject the method returns NULL. the data isn't a wxObject the method returns NULL.
\membersection{wxVariantData::IncRef}\label{wxvariantdataincref}
\func{void}{IncRef}{\void}
Increases reference count. Note that initially wxVariantData has reference count of 1.
\membersection{wxVariantData::Read}\label{wxvariantdataread} \membersection{wxVariantData::Read}\label{wxvariantdataread}
\func{bool}{Read}{\param{ostream\&}{ stream}} \func{bool}{Read}{\param{ostream\&}{ stream}}

View File

@@ -36,6 +36,19 @@
* to allow it to store any type of data. * to allow it to store any type of data.
* Derive from this to provide custom data handling. * Derive from this to provide custom data handling.
* *
* NB: To prevent addition of extra vtbl pointer to wxVariantData,
* we don't multiple-inherit from wxObjectRefData. Instead,
* we simply replicate the wxObject ref-counting scheme.
*
* NB: When you construct a wxVariantData, it will have refcount
* of one. Refcount will not be further increased when
* it is passed to wxVariant. This simulates old common
* scenario where wxVariant took ownership of wxVariantData
* passed to it.
* If you create wxVariantData for other reasons than passing
* it to wxVariant, technically you are not required to call
* DecRef() before deleting it.
*
* TODO: in order to replace wxPropertyValue, we would need * TODO: in order to replace wxPropertyValue, we would need
* to consider adding constructors that take pointers to C++ variables, * to consider adding constructors that take pointers to C++ variables,
* or removing that functionality from the wxProperty library. * or removing that functionality from the wxProperty library.
@@ -47,165 +60,98 @@
class WXDLLIMPEXP_BASE wxVariantData: public wxObject class WXDLLIMPEXP_BASE wxVariantData: public wxObject
{ {
DECLARE_ABSTRACT_CLASS(wxVariantData) friend class wxVariant;
public: public:
wxVariantData()
: wxObject(), m_count(1)
{ }
// Construction & destruction // Override these to provide common functionality
wxVariantData() {}
// Override these to provide common functionality
// Copy to data
virtual void Copy(wxVariantData& data) = 0;
virtual bool Eq(wxVariantData& data) const = 0; virtual bool Eq(wxVariantData& data) const = 0;
#if wxUSE_STD_IOSTREAM #if wxUSE_STD_IOSTREAM
virtual bool Write(wxSTD ostream& str) const = 0; virtual bool Write(wxSTD ostream& str) const { return false; }
#endif #endif
virtual bool Write(wxString& str) const = 0; virtual bool Write(wxString& str) const { return false; }
#if wxUSE_STD_IOSTREAM #if wxUSE_STD_IOSTREAM
virtual bool Read(wxSTD istream& str) = 0; virtual bool Read(wxSTD istream& str) { return false; }
#endif #endif
virtual bool Read(wxString& str) = 0; virtual bool Read(wxString& str) { return false; }
// What type is it? Return a string name. // What type is it? Return a string name.
virtual wxString GetType() const = 0; virtual wxString GetType() const = 0;
// If it based on wxObject return the ClassInfo. // If it based on wxObject return the ClassInfo.
virtual wxClassInfo* GetValueClassInfo() { return NULL; } virtual wxClassInfo* GetValueClassInfo() { return NULL; }
void IncRef() { m_count++; }
void DecRef()
{
if ( --m_count == 0 )
delete this;
}
int GetRefCount() const { return m_count; }
protected:
// Protected dtor should make some incompatible code
// break more louder. That is, they should do data->DecRef()
// instead of delete data.
virtual ~wxVariantData() { }
private:
int m_count;
private:
DECLARE_ABSTRACT_CLASS(wxVariantData)
}; };
/* /*
* wxVariant can store any kind of data, but has some basic types * wxVariant can store any kind of data, but has some basic types
* built in. * built in.
* NOTE: this eventually should have a reference-counting implementation.
* PLEASE, if you change it to ref-counting, make sure it doesn't involve bloating
* this class too much.
*/ */
class WXDLLIMPEXP_BASE wxVariant: public wxObject class WXDLLIMPEXP_BASE wxVariant: public wxObject
{ {
DECLARE_DYNAMIC_CLASS(wxVariant)
public: public:
// Construction & destruction
wxVariant(); wxVariant();
wxVariant(double val, const wxString& name = wxEmptyString);
wxVariant(long val, const wxString& name = wxEmptyString);
#ifdef HAVE_BOOL
wxVariant(bool val, const wxString& name = wxEmptyString);
#endif
wxVariant(char val, const wxString& name = wxEmptyString);
wxVariant(const wxString& val, const wxString& name = wxEmptyString);
wxVariant(const wxChar* val, const wxString& name = wxEmptyString); // Necessary or VC++ assumes bool!
#if WXWIN_COMPATIBILITY_2_4
wxDEPRECATED( wxVariant(const wxStringList& val, const wxString& name = wxEmptyString) );
#endif
wxVariant(const wxList& val, const wxString& name = wxEmptyString); // List of variants
wxVariant(void* ptr, const wxString& name = wxEmptyString); // void* (general purpose)
wxVariant(wxObject* ptr, const wxString& name = wxEmptyString); //wxObject
wxVariant(wxVariantData* data, const wxString& name = wxEmptyString); // User-defined data
#if wxUSE_DATETIME
wxVariant(const wxDateTime& val, const wxString& name = wxEmptyString); // Date
#endif // wxUSE_DATETIME
wxVariant(const wxArrayString& val, const wxString& name = wxEmptyString); // String array
#if wxUSE_ODBC
wxVariant(const DATE_STRUCT* valptr, const wxString& name = wxEmptyString); // DateTime
wxVariant(const TIME_STRUCT* valptr, const wxString& name = wxEmptyString); // DateTime
wxVariant(const TIMESTAMP_STRUCT* valptr, const wxString& name = wxEmptyString); // DateTime
#endif
wxVariant(const wxVariant& variant); wxVariant(const wxVariant& variant);
wxVariant(wxVariantData* data, const wxString& name = wxEmptyString);
virtual ~wxVariant(); virtual ~wxVariant();
// Generic operators // generic assignment
// Assignment
void operator= (const wxVariant& variant); void operator= (const wxVariant& variant);
#if wxUSE_DATETIME
bool operator== (const wxDateTime& value) const;
bool operator!= (const wxDateTime& value) const;
void operator= (const wxDateTime& value) ;
#endif // wxUSE_DATETIME
bool operator== (const wxArrayString& value) const;
bool operator!= (const wxArrayString& value) const;
void operator= (const wxArrayString& value) ;
#if wxUSE_ODBC
void operator= (const DATE_STRUCT* value) ;
void operator= (const TIME_STRUCT* value) ;
void operator= (const TIMESTAMP_STRUCT* value) ;
#endif
// Assignment using data, e.g. // Assignment using data, e.g.
// myVariant = new wxStringVariantData("hello"); // myVariant = new wxStringVariantData("hello");
void operator= (wxVariantData* variantData); void operator= (wxVariantData* variantData);
bool operator== (const wxVariant& variant) const; bool operator== (const wxVariant& variant) const;
bool operator!= (const wxVariant& variant) const; bool operator!= (const wxVariant& variant) const;
// Specific operators
bool operator== (double value) const;
bool operator!= (double value) const;
void operator= (double value) ;
bool operator== (long value) const;
bool operator!= (long value) const;
void operator= (long value) ;
bool operator== (char value) const;
bool operator!= (char value) const;
void operator= (char value) ;
#ifdef HAVE_BOOL
bool operator== (bool value) const;
bool operator!= (bool value) const;
void operator= (bool value) ;
#endif
bool operator== (const wxString& value) const;
bool operator!= (const wxString& value) const;
void operator= (const wxString& value) ;
void operator= (const wxChar* value) ; // Necessary or VC++ assumes bool!
#if WXWIN_COMPATIBILITY_2_4
wxDEPRECATED( bool operator== (const wxStringList& value) const );
wxDEPRECATED( bool operator!= (const wxStringList& value) const );
wxDEPRECATED( void operator= (const wxStringList& value) );
#endif
bool operator== (const wxList& value) const;
bool operator!= (const wxList& value) const;
void operator= (const wxList& value) ;
bool operator== (void* value) const;
bool operator!= (void* value) const;
void operator= (void* value);
bool operator== (wxObject* value) const;
bool operator!= (wxObject* value) const;
void operator= (wxObject* value);
// Treat a list variant as an array
wxVariant operator[] (size_t idx) const;
wxVariant& operator[] (size_t idx) ;
// Implicit conversion to a wxString
inline operator wxString () const { return MakeString(); }
wxString MakeString() const;
// Other implicit conversions
inline operator double () const { return GetDouble(); }
inline operator char () const { return GetChar(); }
inline operator long () const { return GetLong(); }
inline operator bool () const { return GetBool(); }
inline operator void* () const { return GetVoidPtr(); }
// No implicit conversion to wxObject, as that would really
// confuse people between conversion to our contained data
// and downcasting to see our base type.
#if wxUSE_DATETIME
inline operator wxDateTime () const { return GetDateTime(); }
#endif // wxUSE_DATETIME
// Accessors
// Sets/gets name // Sets/gets name
inline void SetName(const wxString& name) { m_name = name; } inline void SetName(const wxString& name) { m_name = name; }
inline const wxString& GetName() const { return m_name; } inline const wxString& GetName() const { return m_name; }
// Tests whether there is data // Tests whether there is data
inline bool IsNull() const { return (m_data == (wxVariantData*) NULL); } bool IsNull() const;
// For compatibility with wxWidgets <= 2.6, this doesn't increase
// reference count.
wxVariantData* GetData() const { return m_data; } wxVariantData* GetData() const { return m_data; }
void SetData(wxVariantData* data) ; void SetData(wxVariantData* data) ;
// make a 'clone' of the object
void Ref(const wxVariant& clone);
// destroy a reference
void UnRef();
// Make NULL (i.e. delete the data)
void MakeNull();
// Delete data and name
void Clear();
// Returns a string representing the type of the variant, // Returns a string representing the type of the variant,
// e.g. "string", "bool", "stringlist", "list", "double", "long" // e.g. "string", "bool", "stringlist", "list", "double", "long"
wxString GetType() const; wxString GetType() const;
@@ -213,31 +159,124 @@ public:
bool IsType(const wxString& type) const; bool IsType(const wxString& type) const;
bool IsValueKindOf(const wxClassInfo* type) const; bool IsValueKindOf(const wxClassInfo* type) const;
// Return the number of elements in a list // write contents to a string (e.g. for debugging)
size_t GetCount() const; wxString MakeString() const;
// Value accessors // double
double GetReal() const ; wxVariant(double val, const wxString& name = wxEmptyString);
inline double GetDouble() const { return GetReal(); }; bool operator== (double value) const;
long GetInteger() const ; bool operator!= (double value) const;
inline long GetLong() const { return GetInteger(); }; void operator= (double value) ;
char GetChar() const ; inline operator double () const { return GetDouble(); }
inline double GetReal() const { return GetDouble(); }
double GetDouble() const;
// long
wxVariant(long val, const wxString& name = wxEmptyString);
wxVariant(int val, const wxString& name = wxEmptyString);
wxVariant(short val, const wxString& name = wxEmptyString);
bool operator== (long value) const;
bool operator!= (long value) const;
void operator= (long value) ;
inline operator long () const { return GetLong(); }
inline long GetInteger() const { return GetLong(); }
long GetLong() const;
// bool
#ifdef HAVE_BOOL
wxVariant(bool val, const wxString& name = wxEmptyString);
bool operator== (bool value) const;
bool operator!= (bool value) const;
void operator= (bool value) ;
inline operator bool () const { return GetBool(); }
bool GetBool() const ; bool GetBool() const ;
wxString GetString() const ;
wxList& GetList() const ;
#if WXWIN_COMPATIBILITY_2_4
wxDEPRECATED( wxStringList& GetStringList() const );
#endif #endif
void* GetVoidPtr() const;
wxObject* GetWxObjectPtr() const; // wxDateTime
#if wxUSE_DATETIME #if wxUSE_DATETIME
wxDateTime GetDateTime() const ; wxVariant(const wxDateTime& val, const wxString& name = wxEmptyString);
#endif // wxUSE_DATETIME #if wxUSE_ODBC
wxVariant(const DATE_STRUCT* valptr, const wxString& name = wxEmptyString);
wxVariant(const TIME_STRUCT* valptr, const wxString& name = wxEmptyString);
wxVariant(const TIMESTAMP_STRUCT* valptr, const wxString& name = wxEmptyString);
#endif
bool operator== (const wxDateTime& value) const;
bool operator!= (const wxDateTime& value) const;
void operator= (const wxDateTime& value) ;
#if wxUSE_ODBC
void operator= (const DATE_STRUCT* value) ;
void operator= (const TIME_STRUCT* value) ;
void operator= (const TIMESTAMP_STRUCT* value) ;
#endif
inline operator wxDateTime () const { return GetDateTime(); }
wxDateTime GetDateTime() const;
#endif
// wxString
wxVariant(const wxString& val, const wxString& name = wxEmptyString);
wxVariant(const wxChar* val, const wxString& name = wxEmptyString); // Necessary or VC++ assumes bool!
bool operator== (const wxString& value) const;
bool operator!= (const wxString& value) const;
void operator= (const wxString& value) ;
void operator= (const wxChar* value) ; // Necessary or VC++ assumes bool!
inline operator wxString () const { return MakeString(); }
wxString GetString() const;
// char (wxChar?)
wxVariant(char val, const wxString& name = wxEmptyString);
bool operator== (char value) const;
bool operator!= (char value) const;
void operator= (char value) ;
inline operator char () const { return GetChar(); }
char GetChar() const ;
// wxArrayString
wxVariant(const wxArrayString& val, const wxString& name = wxEmptyString);
bool operator== (const wxArrayString& value) const;
bool operator!= (const wxArrayString& value) const;
void operator= (const wxArrayString& value);
inline operator wxArrayString () const { return GetArrayString(); }
wxArrayString GetArrayString() const; wxArrayString GetArrayString() const;
// Operations // void*
// Make NULL (i.e. delete the data) wxVariant(void* ptr, const wxString& name = wxEmptyString);
void MakeNull(); bool operator== (void* value) const;
bool operator!= (void* value) const;
void operator= (void* value);
inline operator void* () const { return GetVoidPtr(); }
void* GetVoidPtr() const;
// wxObject*
wxVariant(wxObject* ptr, const wxString& name = wxEmptyString);
bool operator== (wxObject* value) const;
bool operator!= (wxObject* value) const;
void operator= (wxObject* value);
wxObject* GetWxObjectPtr() const;
#if WXWIN_COMPATIBILITY_2_4
wxDEPRECATED( wxVariant(const wxStringList& val, const wxString& name = wxEmptyString) );
wxDEPRECATED( bool operator== (const wxStringList& value) const );
wxDEPRECATED( bool operator!= (const wxStringList& value) const );
wxDEPRECATED( void operator= (const wxStringList& value) );
wxDEPRECATED( wxStringList& GetStringList() const );
#endif
// ------------------------------
// list operations
// ------------------------------
wxVariant(const wxList& val, const wxString& name = wxEmptyString); // List of variants
bool operator== (const wxList& value) const;
bool operator!= (const wxList& value) const;
void operator= (const wxList& value) ;
// Treat a list variant as an array
wxVariant operator[] (size_t idx) const;
wxVariant& operator[] (size_t idx) ;
wxList& GetList() const ;
// Return the number of elements in a list
size_t GetCount() const;
// Make empty list // Make empty list
void NullList(); void NullList();
@@ -257,9 +296,8 @@ public:
// Clear list // Clear list
void ClearList(); void ClearList();
// Implementation
public: public:
// Type conversion // Type conversion
bool Convert(long* value) const; bool Convert(long* value) const;
bool Convert(bool* value) const; bool Convert(bool* value) const;
bool Convert(double* value) const; bool Convert(double* value) const;
@@ -273,6 +311,9 @@ public:
protected: protected:
wxVariantData* m_data; wxVariantData* m_data;
wxString m_name; wxString m_name;
private:
DECLARE_DYNAMIC_CLASS(wxVariant)
}; };
//Since we want type safety wxVariant we need to fetch and dynamic_cast //Since we want type safety wxVariant we need to fetch and dynamic_cast

File diff suppressed because it is too large Load Diff