diff --git a/documentation/pvDataCpp.html b/documentation/pvDataCpp.html index 8c81dff..d07d9a7 100644 --- a/documentation/pvDataCpp.html +++ b/documentation/pvDataCpp.html @@ -10,7 +10,7 @@
TODO
This product is available via the open source license described at the end of this document.
PVData is one of a set of related projects: pvData, pvAccess, and javaIOC. -It describes and implements the data that the other project use. Thus it is -not useful by itself but understanding pvData is required in order to -understand the other projects. The reader should also become familar with -pvAccess and javaIOC, which are located via the same sourceforge site as this -project. Project PVAccess provides network support for transporting pvData. -Project javaIOC provides a memory resident "smart" database of pvData -data.
+It describes and implements the data that the other project use. Thus it is not +useful by itself but understanding pvData is required in order to understand +the other projects. The reader should also become familar with pvAccess and +javaIOC, which are located via the same sourceforge site as this project. +Project PVAccess provides network support for transporting pvData. Project +javaIOC provides a memory resident "smart" database of pvData data.This document describes the C++ implementation of pvData, which was first implemented in Java. A C++ implementation of pvAccess is being developed in -parallel with pvDataCPP. In the future a C++ implementation of javaIOC will -be developed and the name javaIOC will become pvIOC.
+parallel with pvDataCPP. In the future a C++ implementation of javaIOC will be +developed and the name javaIOC will become pvIOC.pvData (Process Variable Data) defines and implements an efficent way to store, access, and transmit memory resident structured data.
@@ -225,13 +223,12 @@ store, access, and transmit memory resident structured data.pvData was initially created to support the javaIOC and was part of the javaIOC project. It is now a separate project that is used by the javaIOC. In addition to the javaIOC, pvData is intended for use by 1) channel access -clients, 2) Interface between client and network, 3) Interface between -network and channel access server, 4) Interface between server and IOC -database. Since it is an interface to data, it could also be used by other -systems, e.g. TANGO, TINE, etc. A high level Physics application can hold -data as pvData. By starting a channel access server, the data can made -available to network clients.
+clients, 2) Interface between client and network, 3) Interface between network +and channel access server, 4) Interface between server and IOC database. Since +it is an interface to data, it could also be used by other systems, e.g. TANGO, +TINE, etc. A high level Physics application can hold data as pvData. By +starting a channel access server, the data can made available to network +clients.pvData contains everything required to support Channel Access and Channel Access clients and servers.
This project has many concepts that are similar to EPICS (Experimental -Physics and Industrial Control System). This C++ implementation uses the -EPICS build system and also EPICS libCom. The directory structure for this -project is a standard EPICS application. The following source directories -appear under pvDataApp:
+Physics and Industrial Control System). This C++ implementation uses the EPICS +build system and also EPICS libCom. The directory structure for this project is +a standard EPICS application. The following source directories appear under +pvDataApp:This section describes a meta language for describing pvData. Currently there are no plans for a parser for the meta language. It is used for -documentation. Also the toString introspection and data methods described -below do present data in this format.
+documentation. Also the toString introspection and data methods described below +do present data in this format. -PVData supports structured data. All data appears as a top level -structure. A structure has an ordered set of fields where each field has a -fieldDef defined as follows:
+PVData supports structured data. All data appears as a top level structure. +A structure has an ordered set of fields where each field has a fieldDef defined as follows:
type fieldName = value // comment
where = value is optional and @@ -375,15 +372,14 @@ line is a comment.
... - Thus a structure array is an array where each element is a structure - but all elements have the same introspection interface. For - introspection the structureDef appears once without and data - valuies. + Thus a structure array is an array where each element is a structure but + all elements have the same introspection interface. For introspection the + structureDef appears once without and data valuies. -Each field can optionally have data values assigned to it. The definition -of the data values depends on the type. For scalars the data value is -whatever is valid for the type.
+Each field can optionally have data values assigned to it. The definition of +the data values depends on the type. For scalars the data value is whatever is +valid for the type.
where each value is a valid scalar data value depending on the type. Thus it is a comma separated set of -values enclosed in [] White space -is permitted surrounding each comma.
+values enclosed in [] White space is +permitted surrounding each comma. -Define the following top level structure:
structure timeStamp
@@ -447,20 +443,20 @@ structure[] structureArrayExample
double y 10.0
Directory pvDataApp/pv has header files that completely describe pvData. -The implementation is provided in directory pvDataApp/factory. Test programs +
Directory pvDataApp/pv has header files that completely describe pvData. The +implementation is provided in directory pvDataApp/factory. Test programs appears on pvDataApp/pvTest.
-A PVStructure is a field that contains an array of subfields. Each field -has code for accessing the field. The interface for each field is PVField or -an interface that extends PVField. Each field also has an introspection -interface, which is Field or an extension of Field. This section describes -the complete set of data and introspection interfaces for pvData.
+A PVStructure is a field that contains an array of subfields. Each field has +code for accessing the field. The interface for each field is PVField or an +interface that extends PVField. Each field also has an introspection interface, +which is Field or an extension of Field. This section describes the complete +set of data and introspection interfaces for pvData.
A class FieldCreate creates introspection objects. A class PVDataCreate creates data objects. A class Convert provides a rich set of methods for @@ -475,14 +471,14 @@ converting and copying data between fields.
This subsection describes pvIntrospect.h
@@ -493,10 +489,10 @@ available. For example when a client connects to a PV, the client library can obtain the reflection information without obtaining any data. Only when a client issues an I/O request will data be available. This separation is especially important for arrays and structures so that a client can discover -the type without requiring that a large data array or structure be -transported over the network. +the type without requiring that a large data array or structure be transported +over the network. -Types are defined as:
enum Type {
@@ -528,17 +524,15 @@ public:
static void toString(StringBuilder buf,ScalarType scalarType);
};
-Type is one of the -following:
+Type is one of the following:
This section describes the reflection interfaces which provide the following:
@@ -621,12 +615,17 @@ following:
class Field : private NoDefaultMethods {
public:
- static ConstructDestructCallback *getConstructDestructCallback();
int getReferenceCount() const;
String getFieldName() const;
Type getType() const;
virtual void toString(StringBuilder buf) const{toString(buf,0);}
virtual void toString(StringBuilder buf,int indentLevel) const;
+ void incReferenceCount() const;
+ void decReferenceCount() const;
+ void dumpReferenceCount(StringBuilder buf,int indentLevel) const;
+protected:
+ Field(String fieldName,Type type);
+ virtual ~Field();
};
class Scalar : public Field{
@@ -637,7 +636,7 @@ public:
protected:
Scalar(String fieldName,ScalarType scalarType);
virtual ~Scalar();
-...
+ ...
};
class ScalarArray : public Field{
@@ -648,7 +647,7 @@ public:
protected:
ScalarArray(String fieldName,ScalarType scalarType);
virtual ~ScalarArray();
-...
+ ...
};
class StructureArray : public Field{
@@ -659,7 +658,7 @@ public:
protected:
StructureArray(String fieldName,StructureConstPtr structure);
virtual ~StructureArray();
-...
+ ...
};
class Structure : public Field {
@@ -673,7 +672,7 @@ public:
protected:
Structure(String fieldName, int numberFields,FieldConstPtrArray fields);
virtual ~Structure();
-...
+ ...
};
class FieldCreate : NoDefaultMethods {
@@ -699,24 +698,36 @@ descriptions:
manages all storage and automatically calls delete when no client is
attached. A few details are discussed in a later section.
Field has the methods:
Scalarhas the methods:
@@ -731,8 +742,7 @@ descriptions:StructureArrayhas the -methods:
+StructureArrayhas the methods:
FieldCreatehas the methods:
The file standardField.h has a class description for creating or sharing -Field objects for standard fields. For each type of standard object two -methods are defined: one with no properties and with properties. The property -field is a comma separated string of property names of the following: alarm, -timeStamp, display, control, and valueAlarm. An example is -"alarm,timeStamp,valueAlarm". The method with properties creates a structure -with fields named fieldName and each of the property names. Each property -field is a structure defining the property. The details about each property -is given in the section named "Property". For example the call:
+Field objects for standard fields. For each type of standard object two methods +are defined: one with no properties and with properties. The property field is +a comma separated string of property names of the following: alarm, timeStamp, +display, control, and valueAlarm. An example is "alarm,timeStamp,valueAlarm". +The method with properties creates a structure with fields named fieldName and +each of the property names. Each property field is a structure defining the +property. The details about each property is given in the section named +"Property". For example the call: StructureConstPtr example = standardField->scalar(
String("value"),
pvDouble,
@@ -853,17 +863,17 @@ extern StandardField * getStandardField();
Where
This section defines the Java Interfaces for accessing the data within a -PV record.
+This section defines the Java Interfaces for accessing the data within a PV +record.
-PVField is the base interface for accessing data. A data structure -consists of a top level PVStructure. Every field of every structure of every -top level structure has a PVField associated with it.
+PVField is the base interface for accessing data. A data structure consists +of a top level PVStructure. Every field of every structure of every top level +structure has a PVField associated with it.
class PostHandler {
public:
virtual void postPut() = 0;
@@ -929,7 +938,6 @@ class PVField
{
public:
virtual ~PVField();
- static ConstructDestructCallback *getConstructDestructCallback();
virtual void setRequester(Requester *prequester);
int getFieldOffset() ;
int getNextFieldOffset() ;
@@ -953,11 +961,10 @@ protected:
private:
};
-PostHandler is a class that -must be implemented by any code that calls setPostHandler. It's single -virtual method. postPut is called -whenever PVField::postPut is -called.
+PostHandler is a class that must +be implemented by any code that calls setPostHandler. It's single virtual +method. postPut is called whenever +PVField::postPut is called.
Requester,Serializable, and NoDefaultMethods are described in a later section.
@@ -969,26 +976,23 @@ are:AuxInfo (Auxillary Information) is information about a field that is application specific. It will not be available outside the application that -implements the database. In particular it will not be made available to -Channel Access. It is used by the database itself to override the default +implements the database. In particular it will not be made available to Channel +Access. It is used by the database itself to override the default implementation of fields. The JavaIOC uses it for attaching support code. Database Configuration and other tools can use it for configuration information. Each Field and each PVField can have have an arbitrary number of @@ -1038,7 +1042,6 @@ auxInfos. An auxInfo is a (key,PVScalar) pair where key is a string.
public: PVAuxInfo(PVField *pvField); ~PVAuxInfo(); - static ConstructDestructCallback *getConstructDestructCallback(); PVField * getPVField(); PVScalar * createInfo(String key,ScalarType scalarType); PVScalarMap getInfos(); @@ -1062,7 +1065,7 @@ private:class PVScalar : public PVField {
public:
virtual ~PVScalar();
@@ -1071,7 +1074,7 @@ protected:
PVScalar(PVStructure *parent,ScalarConstPtr scalar);
};
-The interfaces for primitive data types are:
class PVBoolean : public PVScalar {
@@ -1160,10 +1163,10 @@ protected:
private:
};
-PVArray is the base interface -for all the other PV Array interfaces. It extends PVField and provides the +
PVArray is the base interface for +all the other PV Array interfaces. It extends PVField and provides the additional methods:
class PVArray : public PVField, public SerializableArray {
public:
@@ -1188,8 +1191,7 @@ private:
};
The interface for each array type has get and put methods which have the same arguments except for the data type. For example PVDoubleArray is:
@@ -1233,8 +1235,8 @@ protected: private: }; -Get "exposes" it's internal array by setting data.data and data.offset. -The caller is responsible for copying the array elements. This violates the +
Get "exposes" it's internal array by setting data.data and data.offset. The +caller is responsible for copying the array elements. This violates the principle that objects should not expose their internal data but is done for efficency. For example it makes it possible to copy between arrays with identical element types without requiring an intermediate array.
@@ -1248,9 +1250,9 @@ arguments are:shareData results in the PVArray using the primitive array that is passed -to this method. This is most useful for immutable arrays. In this case the -caller must set the PVArray to be immutable. In the PVArray is not immutable -then it is the applications responsibility to coordinate access to the array. -Again this violates the principle that objects should not expose their -internal data but is important for immutable arrays. For example pvData and -the javaIOC define many enumerated structures where an enumerated structure -has two fields: index and choices. Choices is a PVStringArray that holds the -enumerated choices. Index is a PVInt that is the index of the currently -selected choice. For many enumerated structures the choices is immutable. -Allowing the choices internal String[] to be shared between all the instances -of an enumerated structure saves on storage. Another reason for allowing -shared data is so that an application which processes an array can be -separated into multiple modules that directly access the internal data array -of a PVArray. This can be required for minimizing CPU overhead. In this case -it is the applications responsibility to coordinate access to the array.
+shareData results in the PVArray using the primitive array that is passed to +this method. This is most useful for immutable arrays. In this case the caller +must set the PVArray to be immutable. In the PVArray is not immutable then it +is the applications responsibility to coordinate access to the array. Again +this violates the principle that objects should not expose their internal data +but is important for immutable arrays. For example pvData and the javaIOC +define many enumerated structures where an enumerated structure has two fields: +index and choices. Choices is a PVStringArray that holds the enumerated +choices. Index is a PVInt that is the index of the currently selected choice. +For many enumerated structures the choices is immutable. Allowing the choices +internal String[] to be shared between all the instances of an enumerated +structure saves on storage. Another reason for allowing shared data is so that +an application which processes an array can be separated into multiple modules +that directly access the internal data array of a PVArray. This can be required +for minimizing CPU overhead. In this case it is the applications responsibility +to coordinate access to the array.
-class PVScalarArray : public PVArray {
public:
virtual ~PVScalarArray();
@@ -1471,7 +1473,7 @@ protected:
private:
};
-The interface for a structure is:
class PVStructure : public PVField,public BitSetSerializable {
@@ -1526,22 +1528,22 @@ private:
different field names.
The interface for an array of structures is:
class StructureArrayData {
@@ -1623,7 +1625,7 @@ private:
The other methods are similar to the methods for other array types.
-PVDataCreate
+PVDataCreate
PVDataCreate is an interface that provides methods that create PVField
interfaces. A factory is provided that creates PVDataCreate.
@@ -1663,42 +1665,56 @@ extern PVDataCreate * getPVDataCreate();
A class StandardPVField has methods for creating standard data fields. -Like class StandardField it has two forms of the methods which create a -field, one without properties and one with properties. Again the properties -is some combination of alarm, timeStamp, control, display, and valueAlarm. -And just like StandardField there are methods to create thye standard -properties. The meythods are:
+A class StandardPVField has methods for creating standard data fields. Like +class StandardField it has two forms of the methods which create a field, one +without properties and one with properties. Again the properties is some +combination of alarm, timeStamp, control, display, and valueAlarm. And just +like StandardField there are methods to create thye standard properties. The +meythods are:
class StandardPVField : private NoDefaultMethods {
public:
StandardPVField();
@@ -1746,7 +1762,7 @@ public:
PVStructure * powerSupply(PVStructure *parent);
};
-NOTE about copying immutable array fields. If an entire immutable array field is copied to another array that has the same elementType, both offsets @@ -1856,15 +1872,15 @@ This can be less than len if the PVField array contains less than len elements.
newLine is a convenience method -for code that implements toString -It generates a newline and inserts blanks at the beginning of the newline.
+for code that implements toString It +generates a newline and inserts blanks at the beginning of the newline.All include and definition files in project pvDataCPP appear in namespace:
@@ -1872,7 +1888,7 @@ Management // ... }} -Directory misc has an include file pvTypes.h:
typedef signed char int8; @@ -1915,8 +1931,8 @@ treated like an immutable object, which is what pvData require.The remaining definitions are:
Any class that does not want the compiler to generate default methods can privately extend the following class which is defined in file @@ -1986,50 +2002,54 @@ private: NoDefaultMethods & operator=(const NoDefaultMethods &); }; -
Introspection objects are meant to be shared. The constructors and destructors are all private or protected so that an introspection object can only be created via a call to one of the FieldCreate methods described below. -The introspection implementation, together with AbstractPVField keeps -reference counts and automatically deletes objects when the reference count -goes to 0. Code that uses introspection objects always accesses introspection -objects via pointers never via references or direct access to the object. -When a PVData data object is destroyed then pointers to the introspection -objects associated with the data object are no longer valid.
+The introspection implementation, together with AbstractPVField keeps reference +counts and automatically deletes objects when the reference count goes to 0. +Code that uses introspection objects always accesses introspection objects via +pointers never via references or direct access to the object. When an +introspection interface is created via one of the methods of class FieldCreate +the reference count is set to 1. When any code wants to get an introspection +interface from an existing data object and use it for another data object, i.e. +share the interface, then incReferenceCount MUST be called. -The introspection destructors are all private. When code, normally ~PVField, +is done using an intrispection interface it calls decReferenceCount. If the +field is a structure then it is a recursive call. When the reference count for +a field becomes 0 the field is deleted. Note than user code should never call +decReferenceCount since the destructor for PVField calls it.
+ +All PVData data objects must publically extend AbstractPVField, which does not allow default methods but does have a virtual destructor. It is expected that each data object is "owned" by some entity. For example a pvIOC (not -implemented) database will own all records and thus all PVData data objects -in the database. It is the ONLY entity that will create and destroy the data +implemented) database will own all records and thus all PVData data objects in +the database. It is the ONLY entity that will create and destroy the data objects. All other code only receives pointers to the data objects. Before a -record is deleted any code that is connected to a record is notified before -the record is deleted. After deletion all pointers to data in the record are +record is deleted any code that is connected to a record is notified before the +record is deleted. After deletion all pointers to data in the record are invalid. Similarly pvAccess creates and destroys PVData objects and notifies clients before destroying PVData data objects.
-The classes in property, i.e. alarm, timeStamp, display, and control are -all meant to be free copied and shared. They can be created on the stack. In -most cases it is not necessary to create them on the heap.
+The classes in property, i.e. alarm, timeStamp, display, and control are all +meant to be free copied and shared. They can be created on the stack. In most +cases it is not necessary to create them on the heap.
-Other clases privately extend NoDefaultClasses and are not normally meant -to be extended. Thus they can only be created via "new" and must be destroyed -via "delete". These classes normally implement the static method:
-static ConstructDestructCallback *getConstructDestructCallback();- -
This provides access to how many objects have been constructed and -destructed. This can be used to monitor memory usage.
+Other clases privately extend NoDefaultClasses and are not normally meant to +be extended. Thus they can only be created via "new" and must be destroyed via +"delete".
Assume that code wants to print two fields from a PVStructure:
Example of creating a scalar field.
PVDataCreate *pvDataCreate = getPVDataCreate();
@@ -2087,24 +2107,23 @@ and a timeStamp and alarm. Do it the easy way.
String("timeStamp,alarm"))
Only fields named "value" have properties. A record can have multiple -value fields, which can appear in the top level structure of a record or in a +
Only fields named "value" have properties. A record can have multiple value +fields, which can appear in the top level structure of a record or in a substructure. All other fields in the structure containing a value field are considered properties of the value field. The fieldname is also the property name. The value field can have any type, i.e. scalar, scalarArray, or -structure. Typical property fields are timeStamp, alarm, display, control, -and history The timeStamp is a special case. -If it appears anywhere in the structure -hieraracy above a value field it is a property of the value field. +structure. Typical property fields are timeStamp, alarm, display, control, and +history The timeStamp is a special case. If it appears anywhere in the +structure hieraracy above a value field it is a property of the value field.
-For example the following top level structure has a single value field. -The value field has propertiess alarm, timeStamp, and display.
+For example the following top level structure has a single value field. The +value field has propertiess alarm, timeStamp, and display.
structure counterOutput
structure alarm
structure timeStamp
@@ -2117,9 +2136,9 @@ The value field has propertiess alarm, timeStamp, and display.
double low 0.0
double high 10.0
-The following example has three value fields each with properties alarm -and timeStamp. Voltage, Current, and Power each have a different alarms but -all share the timeStamp.
+The following example has three value fields each with properties alarm and +timeStamp. Voltage, Current, and Power each have a different alarms but all +share the timeStamp.
structure powerSupplyValueStructure
double value
structure alarm
@@ -2131,15 +2150,15 @@ structure powerSupplySimple
powerSupplyValueStructure power
powerSupplyValueStructure current
-The following field names have special meaning, i.e. support properties -for general purpose clients.
+The following field names have special meaning, i.e. support properties for +general purpose clients.
The model allows for device records. A device record has structure fields -that support the PVData data model. For example a powerSupport record can -have fields power, voltage, current that each support the PVData data model. -
+that support the PVData data model. For example a powerSupport record can have +fields power, voltage, current that each support the PVData data model. -Except for enumerated, each property has two files: a property.h and a -pvProperty.h . For example: timeStamp.h and pvTimeStamp.h In each case the property.h -file defined methods for manipulating the property data and the pvProperty.h -provides methods to transfer the property data to/from a pvData structure. -
+pvProperty.h . For example: timeStamp.h +and pvTimeStamp.h In each case the +property.h file defined methods for manipulating the property data and the +pvProperty.h provides methods to transfer the property data to/from a pvData +structure. -All methods copy data via copy by value semantics, i.e. not by pointer or -by reference. No property class calls new or delete and all allow the compiler to +
All methods copy data via copy by value semantics, i.e. not by pointer or by +reference. No property class calls new +or delete and all allow the compiler to generate default methods. All allow a class instance to be generated on the stack. For example the following is permitted:
void example(PVField *pvField) {
@@ -2232,7 +2247,7 @@ stack. For example the following is permitted:
...
}
-A timeStamp is represented by the following structure
structure timeStamp
@@ -2240,26 +2255,25 @@ stack. For example the following is permitted:
int32 nanoSeconds
The Epoch is the posix epoch, i.e. Jan 1, 1970 00:00:00 UTC. Both the -seconds and nanoSeconds are signed integers and thus can be negative. Since -the seconds is kept as a 64 bit integer, it allows for a time much greater -than the present age of the universe. Since the nanoSeconds portion is kept -as a 32 bit integer it is subject to overflow if a value that corresponds to -a value that is greater than a little more than 2 seconds of less that about --2 seconds. The support code always adjust seconds so that the nanoSecconds -part is normlized, i. e. it has is 0<=nanoSeconds<nanoSecPerSec..
+seconds and nanoSeconds are signed integers and thus can be negative. Since the +seconds is kept as a 64 bit integer, it allows for a time much greater than the +present age of the universe. Since the nanoSeconds portion is kept as a 32 bit +integer it is subject to overflow if a value that corresponds to a value that +is greater than a little more than 2 seconds of less that about -2 seconds. The +support code always adjust seconds so that the nanoSecconds part is normlized, +i. e. it has is 0<=nanoSeconds<nanoSecPerSec..Two header files are provided for manipulating time stamps: timeStamp.h and pvTimeStamp.h timeStamp.h defines a time stamp independent of pvData, i.e. it is a generally useful class for manipulating -timeStamps. pvTimeStamp.h is a -class that can be attached to a time stamp pvData structure. It provides get -and set methods to get/set a TimeStamp as defined by pvTimeStamp.h is a class +that can be attached to a time stamp pvData structure. It provides get and set +methods to get/set a TimeStamp as defined by timeStamp.h
-This provides
extern int32 milliSecPerSec; @@ -2300,12 +2314,10 @@ public:where
TimeStamp acts like a primitive. It can be allocated on the stack and the -compiler is free to generate default methods, i.e. copy constructor, -assignment constructor, and destructor.
+compiler is free to generate default methods, i.e. copy constructor, assignment +constructor, and destructor.One use for TimeStamp is to time how long a section of code takes to execute. This is done as follows:
@@ -2363,8 +2375,7 @@ execute. This is done as follows: endTime.getCurrent(); double time = TimeStamp::diff(endTime,startTime); -class PVTimeStamp {
public:
PVTimeStamp();
@@ -2383,14 +2394,14 @@ public:
where
An alarm structure is defined as follows:
structure alarm
int32 severity
String message
-Note that severity is NOT defined as an enumerated structure. The reason -is performance, i. e. prevent passing the array of choice strings everywhere. -The file alarm.h provides the -choice strings. Thus all code that needs to know about alarms share the exact -same choice strings.
+Note that severity is NOT defined as an enumerated structure. The reason is +performance, i. e. prevent passing the array of choice strings everywhere. The +file alarm.h provides the choice +strings. Thus all code that needs to know about alarms share the exact same +choice strings.
Two header files are provided for manipulating alarms: alarm.h and pvAlarm.h alarm.h defines a time stamp independent of pvData, i.e. it is a generally useful class for manipulating alarms. pvAlarm.h is a class that can be -attached to a time stamp pvData structure. It provides get and set methods to -get/set a Alarm as defined by alarm.h
+style="font-family: courier;">pvAlarm.h is a class that can be attached +to a time stamp pvData structure. It provides get and set methods to get/set a +Alarm as defined by alarm.h -enum AlarmSeverity {
noAlarm,minorAlarm,majorAlarm,invalidAlarm
};
@@ -2461,7 +2471,7 @@ public:
class PVAlarm {
public:
PVAlarm() : pvSeverity(0),pvMessage(0) {}
@@ -2491,15 +2501,15 @@ public:
where
Control information is represented by the following structure
structure control @@ -2523,14 +2533,14 @@ public:Two header files are provided for manipulating controls: control.h and pvControl.h control.h defines a time stamp -independent of pvData, i.e. it is a generally useful class for manipulating -controls. pvControl.h is a class -that can be attached to a time stamp pvData structure. It provides get and -set methods to get/set a Control as defined by control.h defines a time stamp independent +of pvData, i.e. it is a generally useful class for manipulating controls. pvControl.h is a class that can be +attached to a time stamp pvData structure. It provides get and set methods to +get/set a Control as defined by control.h
-control.h
+control.h
class Control { public: Control(); @@ -2555,8 +2565,7 @@ public:
class PVControl {
public:
PVControl();
@@ -2575,15 +2584,15 @@ public:
where
Display information is represented by the following structure
structure display @@ -2612,12 +2621,12 @@ style="font-family: courier;">display.h and pvDisplay.h display.h defines display information independent of pvData, i.e. it is a generally useful class for manipulating -display infomation. pvDisplay.h is -a class that can be attached to a display pvData structure. It provides get -and set methods to get/set a Diaplay as defined by pvDisplay.h is a +class that can be attached to a display pvData structure. It provides get and +set methods to get/set a Diaplay as defined by diaplay.h -display.h
+display.h
class Display { public: Display(); @@ -2660,8 +2669,7 @@ public:
class PVDisplay {
public:
PVDisplay()
@@ -2680,15 +2688,15 @@ public:
where
An enumerated structure is a structure that has fields:
structure @@ -2745,8 +2753,8 @@ public:
Drectory factory has code that implements everything described by the include files in directory pv
-FieldCreateFactory automatically creates a single instance of FieldCreate and provides a method to get the interface.
-PVDataCreateFactory automatically creates a single instance of -PVDataCreate and provides a method to get the interface.
+PVDataCreateFactory automatically creates a single instance of PVDataCreate +and provides a method to get the interface.
PVAuxInfoImpl implements auxInfo.
Convert automatically creates a single instance of Convert and provides a method to get the interface.
-This is an abstract base class for implementing PVField interfaces. It -MUST be the base class for any class that extends PVField.
+This is an abstract base class for implementing PVField interfaces. It MUST +be the base class for any class that extends PVField.
-This is an abstract base class for implementing scalar data fields. It -MUST be the base class for any class that implements a scalar data field.
+This is an abstract base class for implementing scalar data fields. It MUST +be the base class for any class that implements a scalar data field.
-This is an abstract base class for implementing array data fields. It MUST be the base class for any class implements array data fields.
-This is an abstract base class for implementing scalar array data fields. -It MUST be the base class for any class implements scalar array data fields. -
+This is an abstract base class for implementing scalar array data fields. It +MUST be the base class for any class implements scalar array data fields.
-BasePVStructure is a base class for any code that implements PVStructure. Any code that implements PVStructure MUST extend this class.
-For each scalar type there is a base class that implements it. The -complete list is:
+For each scalar type there is a base class that implements it. The complete +list is:
For each scalar array type there is a base class that implements it. The complete list is:
@@ -2850,10 +2856,10 @@ complete list is:This package provides utility code:
Note that directory testApp/misc has test code for all the classes in -misc. The test code also can be used as examples.
+Note that directory testApp/misc has test code for all the classes in misc. +The test code also can be used as examples.
-This is adapted from the java.util.BitSet. bitSet.h is:
class BitSet /*: public Serializable*/ {
@@ -2938,11 +2944,10 @@ private:
where
Clears all of the bits in this bitSet whose corresponding bit is - set in the specified bitSet.
+Clears all of the bits in this bitSet whose corresponding bit is set + in the specified bitSet.
A ByteBuffer is used to serialize and deserialize primitive data. File byteBuffer.h is:
@@ -3040,7 +3044,7 @@ private:x
-This class provides coordinates activity between threads. One thread can wait for the event and the other signals the event.
@@ -3048,7 +3052,6 @@ wait for the event and the other signals the event. public: Event(bool full); ~Event(); - static ConstructDestructCallback *getConstructDestructCallback(); void signal(); bool wait (); /* blocks until full */ bool wait ( double timeOut ); /* false if empty at time out */ @@ -3062,9 +3065,6 @@ private:File epicsException.h describes:
class BaseException : public std::exception {
@@ -3094,10 +3094,10 @@ private:
x
-Executor
+Executor
-An Executor is a thread that can execute commands. The user can request
-that a single command be executed.
+An Executor is a thread that can execute commands. The user can request that
+a single command be executed.
class ExecutorNode;
class Command {
@@ -3109,27 +3109,23 @@ class Executor : private NoDefaultMethods {
public:
Executor(String threadName,ThreadPriority priority);
~Executor();
- static ConstructDestructCallback *getConstructDestructCallback();
ExecutorNode * createNode(Command *command);
void execute(ExecutorNode *node);
private:
class ExecutorPvt *pImpl;
};
-Command is a class that must be implemented by the code that calls
-execute. It contains the single virtual method command, which is the command
-to execute.
+Command is a class that must be implemented by the code that calls execute.
+It contains the single virtual method command, which is the command to
+execute.
Executor has the methods:
LinkedList implements a double linked list that requires a user to -allocate the nodes. It is more efficent that std::list. linkedList.h is a -template that is both a complete description and definition. It uses -linkedListVoid for method definitions. linkedListVoid is not meant for use -except via linkedList. Note, however, that linkedListVoid does have both a -node and a list static method getConstructDestructCallback, which allows -access to how many nodes and lists have been created and destroyed.
+LinkedList implements a double linked list that requires a user to allocate +the nodes. It is more efficent that std::list. linkedList.h is a template that +is both a complete description and definition. It uses linkedListVoid for +method definitions. linkedListVoid is not meant for use except via +linkedList.
-A node can only be on one list at a time but can be put, at different -times, on different lists as long as they all hold the same type of objects. -An exception is thrown if an attempt is made to put a node on a list if the -node is already on a list.
+A node can only be on one list at a time but can be put, at different times, +on different lists as long as they all hold the same type of objects. An +exception is thrown if an attempt is made to put a node on a list if the node +is already on a list.
template <typename T>
class LinkedList;
@@ -3210,8 +3204,8 @@ public:
lock.h is:
class Mutex {
@@ -3269,17 +3261,17 @@ private:
Mutex *mutexPtr;
};
-This is a complete description and definition of lock and mutex. These -make it easy to have a lock that is as easy to use as Java synchronize. To -protect some object just create a Mutex for the object and then in any method -to be synchronized just have code like:
+This is a complete description and definition of lock and mutex. These make +it easy to have a lock that is as easy to use as Java synchronize. To protect +some object just create a Mutex for the object and then in any method to be +synchronized just have code like:
class SomeClass {
private
Mutex mutex;
-...
+ ...
public
SomeClass() : mutex(Mutex()) {}
-...
+ ...
void method()
{
Lock xx(&mutex);
@@ -3298,9 +3290,9 @@ once. This can be implemented as follows:
// initialization
}
-class MessageNode {
public:
String getMessage() const;
@@ -3311,7 +3303,6 @@ class MessageQueue : private NoDefaultMethods {
public:
MessageQueue(int size);
~MessageQueue();
- static ConstructDestructCallback *getConstructDestructCallback();
MessageNode *get();
// must call release before next get
void release();
@@ -3322,7 +3313,7 @@ public:
int getClearOverrun();
};
-This is for use by code that wants to handle messages without blocking higher priority threads.
@@ -3363,11 +3354,11 @@ higher priority threads.Look at miscTest/testMessageQueue.cpp for an example.
-If a class privately extends this class then the compiler can not create -any of the following: default constructor, default copy constructror, or -default assignment contructor.
+If a class privately extends this class then the compiler can not create any +of the following: default constructor, default copy constructror, or default +assignment contructor.
/* This is based on Item 6 of
* Effective C++, Third Edition, Scott Meyers
*/
@@ -3382,7 +3373,7 @@ default assignment contructor.
NoDefaultMethods & operator=(const NoDefaultMethods &);
};
-This provides typedefs for integers and String.
typedef signed char int8; @@ -3410,7 +3401,7 @@ typedef String* StringArray;
A PVField extends Requester. Requester is present so that when database errors are found there is someplace to send a message.
@@ -3440,10 +3431,10 @@ public:This is a helper class for serialization, which is required for sending -and receiving pvData over the nerwork.
+This is a helper class for serialization, which is required for sending and +receiving pvData over the nerwork.
class SerializeHelper : public NoDefaultMethods {
public:
static void writeSize(int s, ByteBuffer* buffer,
@@ -3511,7 +3502,7 @@ properly implemented.
x
-Show Constructors and
+Show Constructors and
Destructors
This is a facility that allows a class to report how many objects of that
@@ -3520,52 +3511,63 @@ class have been created and destroyed. This can help find memory leaks.
class ConstructDestructCallback : private NoDefaultMethods {
public:
- ConstructDestructCallback(
- String name,
- getTotal construct,
- getTotal destruct,
- getTotal reference);
String getConstructName();
int64 getTotalConstruct();
int64 getTotalDestruct();
int64 getTotalReferenceCount();
private:
- ~ConstructDestructCallback();
- String name;
- getTotal construct;
- getTotal destruct;
- getTotal reference;
};
class ShowConstructDestruct : private NoDefaultMethods {
public:
- static void constuctDestructTotals(FILE *fd);
- static void registerCallback(ConstructDestructCallback *callback);
+ static void registerCallback(
+ String name,
+ getTotalFunc construct,
+ getTotalFunc destruct,
+ getTotalFunc reference,
+ deleteStaticFunc deleteFunc);
+ ConstructDestructCallback* getConstructDestructCallback(String name);
+ void constuctDestructTotals(FILE *fd);
+ static void showDeleteStaticExit(FILE *fd);
private:
- ShowConstructDestruct();
- friend ShowConstructDestruct* getShowConstructDestruct();
};
extern ShowConstructDestruct* getShowConstructDestruct();
-ConstructDestructCallback is implemented by a class that keeps track of -how many instances of the class has been created and how many destroyed. The -clas must implement this class and register it with ShowConstructDestruct. To -see an example of how this is implemented look at misc/thread.cpp.
+ConstructDestructCallback is implemented by ShowConstructDestruct. MARTY +EDIT how many instances of the class has been created and how many destroyed. +The clas must implement this class and register it with ShowConstructDestruct. +To see an example of how this is implemented look at misc/thread.cpp.
-Classes that implement this class also include a static method that makes -ConstructDestructCallback available to code that wants look at the memory -usage of a particular class.
+The public methods of ConstructDestructCallback are:
+ShowConstructDestruct is the class that reports the memory uasge of all -registered classes. It can be called as folows:
-getShowConstructDestruct()->constuctDestructTotals(fd);+
The public methods of ShowConstructDestruct are:
+Status provides a way to pass status back to client code. It is new and -not currently used by pvData but may be in the future. It is used by code -that uses pvData.
+Status provides a way to pass status back to client code. It is new and not +currently used by pvData but may be in the future. It is used by code that uses +pvData.
NOT IMPLEMENTED
The Status methods are:
@@ -3592,9 +3594,9 @@ that uses pvData. status optimization. -enum ThreadPriority {
lowestPriority,
lowerPriority,
@@ -3611,7 +3613,7 @@ public:
static int getEpicsPriority(ThreadPriority threadPriority);
};
-class Runnable {
public:
virtual void run() = 0;
@@ -3623,7 +3625,6 @@ class Thread : private NoDefaultMethods {
public:
Thread(String name,ThreadPriority priority,Runnable *runnableReady);
~Thread();
- static ConstructDestructCallback *getConstructDestructCallback();
String getName();
ThreadPriority getPriority();
static void showThreads(StringBuilder buf);
@@ -3631,46 +3632,42 @@ public:
private:
};
-Runnable must be implement by code that wants to be run via a thread. It -has one virtual method: run. Run is the code that is run as a thread. When -run compeletes it can not be restarted. If code wants to delete a thread then -it MUST arrange that the run returns before the thread can be deleted. An +
Runnable must be implement by code that wants to be run via a thread. It has +one virtual method: run. Run is the code that is run as a thread. When run +compeletes it can not be restarted. If code wants to delete a thread then it +MUST arrange that the run returns before the thread can be deleted. An exception is thrown if run remains active when delete is called.
Thread has the methods:
delete pthread;
TimeFunction is a facility that measures the average number of seconds a function call requires. When timeCall is called, it calls function in a loop. -It starts with a loop of one iteration. If the total elapsed time is less -then .1 seconds it increases the number of iterrations by a factor of 10. It -keeps repeating until the elapsed time is greater than .1 seconds. It returns -the average number of seconds per call.
+It starts with a loop of one iteration. If the total elapsed time is less then +.1 seconds it increases the number of iterrations by a factor of 10. It keeps +repeating until the elapsed time is greater than .1 seconds. It returns the +average number of seconds per call.class TimeFunctionRequester {
public:
virtual void function() = 0;
@@ -3705,7 +3702,7 @@ long a function takes. It has the single method:
one second to call it ntimes.
-Timer
+Timer
This provides a general purpose timer. It allows a user callback to be
called after a delay or periodically.
@@ -3719,7 +3716,6 @@ class TimerNode : private NoDefaultMethods {
public:
TimerNode(TimerCallback *timerCallback);
~TimerNode();
- static ConstructDestructCallback *getConstructDestructCallback();
void cancel();
bool isScheduled();
private:
@@ -3729,28 +3725,27 @@ class Timer : private NoDefaultMethods {
public:
Timer(String threadName, ThreadPriority priority);
~Timer();
- static ConstructDestructCallback *getConstructDestructCallback();
void scheduleAfterDelay(TimerNode *timerNode,double delay);
void schedulePeriodic(TimerNode *timerNode,double delay,double period);
private:
};
-TimerCallback must be implemented by the user. It has the following -methods:
+TimerCallback must be implemented by the user. It has the following methods: +
In order to schedule a callback client code must allocate a TimerNode It -can be used to schedule multiple callbacks. It has the methods:
+In order to schedule a callback client code must allocate a TimerNode It can +be used to schedule multiple callbacks. It has the methods:
delete timerNode;
This provides a queue which has an immutable capacity. When the queue is full the user code is expected to keep using the current element until a new @@ -3831,14 +3820,14 @@ public: the caller until setUsed is called.
A queue is created as follows:
@@ -3870,10 +3859,10 @@ public: }The following is also provided:
class BitSetUtil : private NoDefaultMethods {
@@ -3889,20 +3878,20 @@ currently has only one method:
MultiChoice defines an array of strings and a bit set that selects an arbitrary set of the choices. This will be implemented if the java version is @@ -3910,7 +3899,7 @@ accepted.
NOT DONE
Copyright (c) 2008 Martin R. Kraimer Copyright (c) 2007 Control System Laboratory, diff --git a/pvDataApp/Makefile b/pvDataApp/Makefile index 7a0b54a..9fc2015 100644 --- a/pvDataApp/Makefile +++ b/pvDataApp/Makefile @@ -28,11 +28,11 @@ INC += messageQueue.h INC += destroyable.h INC += status.h +LIBSRCS += showConstructDestruct.cpp LIBSRCS += byteBuffer.cpp LIBSRCS += bitSet.cpp LIBSRCS += requester.cpp LIBSRCS += serializeHelper.cpp -LIBSRCS += showConstructDestruct.cpp LIBSRCS += linkedListVoid.cpp LIBSRCS += event.cpp LIBSRCS += thread.cpp diff --git a/pvDataApp/factory/AbstractPVField.h b/pvDataApp/factory/AbstractPVField.h index 6631bad..1e4f9cb 100644 --- a/pvDataApp/factory/AbstractPVField.h +++ b/pvDataApp/factory/AbstractPVField.h @@ -12,6 +12,7 @@ #include#include "pvData.h" #include "factory.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { @@ -19,31 +20,29 @@ static String notImplemented("not implemented"); static volatile int64 totalConstruct = 0; static volatile int64 totalDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; static int64 getTotalConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalConstruct; } static int64 getTotalDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalDestruct; } -static ConstructDestructCallback *pConstructDestructCallback; - static void init() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pConstructDestructCallback = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( String("pvField"), - getTotalConstruct,getTotalDestruct,0); + getTotalConstruct,getTotalDestruct,0,0); } } @@ -67,13 +66,12 @@ PVFieldPvt::PVFieldPvt(PVStructure *parent,FieldConstPtr field) pvAuxInfo(0), immutable(false),requester(0),postHandler(0) { - field->incReferenceCount(); } PVFieldPvt::~PVFieldPvt() { - if(pvAuxInfo!=0) delete pvAuxInfo; - field->decReferenceCount(); + if(pvAuxInfo!=0) delete pvAuxInfo; + if(parent==0) field->decReferenceCount(); } @@ -82,24 +80,17 @@ PVField::PVField(PVStructure *parent,FieldConstPtr field) : pImpl(new PVFieldPvt(parent,field)) { init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalConstruct++; } PVField::~PVField() { - Lock xx(globalMutex); + Lock xx(&globalMutex); totalDestruct++; delete pImpl; } -ConstructDestructCallback *PVField::getConstructDestructCallback() -{ - init(); - return pConstructDestructCallback; -} - - String PVField::getRequesterName() { static String none("none"); @@ -322,18 +313,22 @@ void PVField::computeOffset(PVField * pvField,int offset) { void PVField::replaceStructure(PVStructure *pvStructure,int length) { - PVFieldPtrArray pvFields = pvStructure->getPVFields(); - FieldConstPtrArray newFields = new FieldConstPtr[length]; - for(int i=0; i getField(); - } - StructureConstPtr newStructure = getFieldCreate()->createStructure( - pImpl->field->getFieldName(),length, newFields); - pImpl->field = newStructure; - PVStructure *parent = pImpl->parent; - if(parent!=0) { - parent->replaceStructure(parent,parent->getStructure()->getNumberFields()); - } + PVFieldPtrArray pvFields = pvStructure->getPVFields(); + FieldConstPtrArray newFields = new FieldConstPtr[length]; + for(int i=0; i getField(); + } + StructureConstPtr newStructure = getFieldCreate()->createStructure( + pImpl->field->getFieldName(),length, newFields); + PVStructure *parent = pImpl->parent; + if(parent==0) { + pImpl->field->decReferenceCount(); + } + pImpl->field = newStructure; + if(parent!=0) { + parent->replaceStructure( + parent,parent->getStructure()->getNumberFields()); + } } diff --git a/pvDataApp/factory/BasePVStructure.h b/pvDataApp/factory/BasePVStructure.h index fd07712..5256e83 100644 --- a/pvDataApp/factory/BasePVStructure.h +++ b/pvDataApp/factory/BasePVStructure.h @@ -54,22 +54,17 @@ namespace epics { namespace pvData { switch(field->getType()) { case scalar: { ScalarConstPtr scalar = (ScalarConstPtr)field; - pvFields[i] = pvDataCreate->createPVScalar(this, - field->getFieldName(),scalar->getScalarType()); + pvFields[i] = pvDataCreate->createPVScalar(this,scalar); break; } case scalarArray: { ScalarArrayConstPtr array = (ScalarArrayConstPtr)field; - ScalarType elementType = array->getElementType(); - pvFields[i] = pvDataCreate->createPVScalarArray(this, - field->getFieldName(),elementType); + pvFields[i] = pvDataCreate->createPVScalarArray(this,array); break; } case structure: { StructureConstPtr structPtr = (StructureConstPtr)field; - int numberFields = structPtr->getNumberFields(); - pvFields[i] = pvDataCreate->createPVStructure(this, - field->getFieldName(), numberFields,structPtr->getFields()); + pvFields[i] = pvDataCreate->createPVStructure(this, structPtr); break; } case structureArray: { diff --git a/pvDataApp/factory/BasePVStructureArray.h b/pvDataApp/factory/BasePVStructureArray.h index b904525..68eb9d9 100644 --- a/pvDataApp/factory/BasePVStructureArray.h +++ b/pvDataApp/factory/BasePVStructureArray.h @@ -57,16 +57,16 @@ namespace epics { namespace pvData { structureArrayData(new StructureArrayData()), value(new PVStructurePtr[0]) { - structureArray->incReferenceCount(); } BasePVStructureArray::~BasePVStructureArray() { - structureArray->decReferenceCount(); delete structureArrayData; int length = getLength(); for(int i=0; i getStructure(); for(int i=0; i value = value; + for(int i=0; i #include #include "pvIntrospect.h" +#include "convert.h" #include "factory.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { @@ -27,26 +29,27 @@ public : FieldPvt(String fieldName,Type type); String fieldName; Type type; - mutable volatile int referenceCount; + int referenceCount; }; FieldPvt::FieldPvt(String fieldName,Type type) - : fieldName(fieldName),type(type),referenceCount(0) { } + : fieldName(fieldName),type(type),referenceCount(1) { } static volatile int64 totalReferenceCount = 0; static volatile int64 totalConstruct = 0; static volatile int64 totalDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; static int64 getTotalConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalConstruct; } static int64 getTotalDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalDestruct; } @@ -55,17 +58,15 @@ static int64 getTotalReferenceCount() return totalReferenceCount; } -static ConstructDestructCallback *pConstructDestructCallback; - static void init() { - static Mutex mutex = Mutex(); + static Mutex mutex; Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pConstructDestructCallback = new ConstructDestructCallback( + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( String("field"), - getTotalConstruct,getTotalDestruct,getTotalReferenceCount); + getTotalConstruct,getTotalDestruct,getTotalReferenceCount,0); } } @@ -73,20 +74,21 @@ static void init() Field::Field(String fieldName,Type type) : pImpl(new FieldPvt(fieldName,type)) { - Lock xx(globalMutex); + Lock xx(&globalMutex); totalConstruct++; } Field::~Field() { - Lock xx(globalMutex); + Lock xx(&globalMutex); totalDestruct++; // note that compiler automatically calls destructor for fieldName - delete pImpl; if(debugLevel==highDebug) printf("~Field %s\n",pImpl->fieldName.c_str()); + delete pImpl; + pImpl = 0; } int Field::getReferenceCount() const { - Lock xx(globalMutex); + Lock xx(&globalMutex); return pImpl->referenceCount; } @@ -95,23 +97,59 @@ String Field::getFieldName() const {return pImpl->fieldName;} Type Field::getType() const {return pImpl->type;} void Field::incReferenceCount() const { - Lock xx(globalMutex); + Lock xx(&globalMutex); pImpl->referenceCount++; totalReferenceCount++; + if(pImpl->type!=structure) return; + StructureConstPtr structure = static_cast (this); + FieldConstPtrArray fields = structure->getFields(); + int numberFields = structure->getNumberFields(); + for(int i=0; i incReferenceCount(); + } } void Field::decReferenceCount() const { - Lock xx(globalMutex); - if(pImpl->referenceCount<=0) { + Lock xx(&globalMutex); + if(pImpl->referenceCount<=0) { String message("logicError field "); message += pImpl->fieldName; throw std::logic_error(message); - } - pImpl->referenceCount--; + } + pImpl->referenceCount--; totalReferenceCount--; - if(pImpl->referenceCount==0) delete this; + if(pImpl->type!=structure) { + if(pImpl->referenceCount==0) { + delete this; + } + return; + } + StructureConstPtr structure = static_cast (this); + FieldConstPtrArray fields = structure->getFields(); + int numberFields = structure->getNumberFields(); + for(int i=0; i decReferenceCount(); + } + if(pImpl->referenceCount==0) { + delete this; + } } +void Field:: dumpReferenceCount(StringBuilder buffer,int indentLevel) const { + *buffer += getFieldName(); + char buf[40]; + sprintf(buf," referenceCount %d",getReferenceCount()); + *buffer += buf; + if(pImpl->type!=structure) return; + Convert *convert = getConvert(); + StructureConstPtr structure = static_cast (this); + FieldConstPtrArray fields = structure->getFields(); + int numberFields = structure->getNumberFields(); + for(int i=0; i newLine(buffer,indentLevel+1); + fields[i]->dumpReferenceCount(buffer,indentLevel +1); + } +} void Field::toString(StringBuilder buffer,int indentLevel) const{ *buffer += " "; @@ -217,7 +255,6 @@ void ScalarArray::toString(StringBuilder buffer,int indentLevel) const{ StructureArray::StructureArray(String fieldName,StructureConstPtr structure) : Field(fieldName,structureArray),pstructure(structure) { - pstructure->incReferenceCount(); } StructureArray::~StructureArray() { @@ -237,7 +274,7 @@ Structure::Structure (String fieldName, int numberFields, FieldConstPtrArray infields) : Field(fieldName,structure), numberFields(numberFields), - fields(new FieldConstPtr[numberFields]) + fields(infields) { for(int i=0; i incReferenceCount(); } - this->incReferenceCount(); } Structure::~Structure() { if(debugLevel==highDebug) printf("~Structure %s\n",Field::getFieldName().c_str()); for(int i=0; i decReferenceCount(); + fields[i] = 0; } delete[] fields; } @@ -363,7 +396,7 @@ FieldCreate::FieldCreate() } FieldCreate * getFieldCreate() { - static Mutex mutex = Mutex(); + static Mutex mutex; Lock xx(&mutex); if(fieldCreate==0) fieldCreate = new FieldCreate(); diff --git a/pvDataApp/factory/PVAuxInfoImpl.cpp b/pvDataApp/factory/PVAuxInfoImpl.cpp index 0607881..0df4fff 100644 --- a/pvDataApp/factory/PVAuxInfoImpl.cpp +++ b/pvDataApp/factory/PVAuxInfoImpl.cpp @@ -13,36 +13,36 @@ #include "convert.h" #include "factory.h" #include "lock.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { static volatile int64 totalConstruct = 0; static volatile int64 totalDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; static int64 getTotalConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalConstruct; } static int64 getTotalDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalDestruct; } -static ConstructDestructCallback *pConstructDestructCallback; - static void init() { static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pConstructDestructCallback = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( String("pvAuxInfo"), - getTotalConstruct,getTotalDestruct,0); + getTotalConstruct,getTotalDestruct,0,0); } } @@ -62,12 +62,12 @@ PVAuxInfo::PVAuxInfo(PVField *pvField) : pImpl(new PVAuxInfoPvt(pvField)) { init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalConstruct++; } PVAuxInfo::~PVAuxInfo() { - Lock xx(globalMutex); + Lock xx(&globalMutex); totalDestruct++; map_iterator i = pImpl->theMap.begin(); while(i!=pImpl->theMap.end()) { @@ -82,12 +82,6 @@ PVField * PVAuxInfo::getPVField() { return pImpl->pvField; } -ConstructDestructCallback *PVAuxInfo::getConstructDestructCallback() -{ - init(); - return pConstructDestructCallback; -} - PVScalar * PVAuxInfo::createInfo(String key,ScalarType scalarType) { map_iterator i = pImpl->theMap.find(key); diff --git a/pvDataApp/factory/PVDataCreateFactory.cpp b/pvDataApp/factory/PVDataCreateFactory.cpp index 9b907ee..9e229e8 100644 --- a/pvDataApp/factory/PVDataCreateFactory.cpp +++ b/pvDataApp/factory/PVDataCreateFactory.cpp @@ -122,6 +122,7 @@ PVScalar *PVDataCreate::createPVScalar(PVStructure *parent, PVScalar *PVDataCreate::createPVScalar(PVStructure *parent, String fieldName,PVScalar * scalarToClone) { + scalarToClone->getField()->incReferenceCount(); PVScalar *pvScalar = createPVScalar(parent,fieldName, scalarToClone->getScalar()->getScalarType()); convert->copyScalar(scalarToClone, pvScalar); @@ -174,6 +175,7 @@ PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent, PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent, String fieldName,PVScalarArray * arrayToClone) { + arrayToClone->getField()->incReferenceCount(); PVScalarArray *pvArray = createPVScalarArray(parent,fieldName, arrayToClone->getScalarArray()->getElementType()); convert->copyScalarArray(arrayToClone,0, pvArray,0,arrayToClone->getLength()); @@ -199,7 +201,8 @@ PVStructureArray *PVDataCreate::createPVStructureArray(PVStructure *parent, PVStructure *PVDataCreate::createPVStructure(PVStructure *parent, StructureConstPtr structure) { - return new BasePVStructure(parent,structure); + PVStructure *pvStructure = new BasePVStructure(parent,structure); + return pvStructure; } PVStructure *PVDataCreate::createPVStructure(PVStructure *parent, @@ -215,20 +218,23 @@ PVStructure *PVDataCreate::createPVStructure(PVStructure *parent, { FieldConstPtrArray fields = 0; int numberFields = 0; + PVStructure *pvStructure = 0;; if(structToClone==0) { fields = new FieldConstPtr[0]; + StructureConstPtr structure = fieldCreate->createStructure( + fieldName,numberFields,fields); + pvStructure = new BasePVStructure(parent,structure); } else { - fields = structToClone->getStructure()->getFields(); - numberFields = structToClone->getStructure()->getNumberFields(); + StructureConstPtr structure = structToClone->getStructure(); + structure->incReferenceCount(); + pvStructure = new BasePVStructure(parent,structure); + convert->copyStructure(structToClone,pvStructure); } - StructureConstPtr structure = fieldCreate->createStructure(fieldName,numberFields,fields); - PVStructure *pvStructure = new BasePVStructure(parent,structure); - if(structToClone!=0) convert->copyStructure(structToClone,pvStructure); return pvStructure; } PVDataCreate * getPVDataCreate() { - static Mutex mutex = Mutex(); + static Mutex mutex; Lock xx(&mutex); if(pvDataCreate==0){ diff --git a/pvDataApp/factory/StandardField.cpp b/pvDataApp/factory/StandardField.cpp index 6b176a1..0289efb 100644 --- a/pvDataApp/factory/StandardField.cpp +++ b/pvDataApp/factory/StandardField.cpp @@ -10,12 +10,16 @@ #include #include "pvIntrospect.h" #include "standardField.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { +static Mutex globalMutex; +static bool notInited = true; +static StandardField* standardField = 0; + static String notImplemented("not implemented"); static FieldCreate* fieldCreate = 0; -static StandardField* standardField = 0; static String valueFieldName("value"); // following are preallocated structures @@ -33,6 +37,7 @@ static StructureConstPtr floatAlarmField = 0; static StructureConstPtr doubleAlarmField = 0; static StructureConstPtr enumeratedAlarmField = 0; + static void createAlarm() { FieldConstPtrArray fields = new FieldConstPtr[2]; fields[0] = fieldCreate->createScalar(String("severity"),pvInt); @@ -245,11 +250,11 @@ static StructureConstPtr createProperties(String fieldName,FieldConstPtr field,S FieldConstPtrArray fields = new FieldConstPtr[numFields]; int next = 0; fields[next++] = field; - if(gotAlarm) fields[next++] = alarmField; - if(gotTimeStamp) fields[next++] = timeStampField; - if(gotDisplay) fields[next++] = displayField; - if(gotControl) fields[next++] = controlField; - if(gotValueAlarm) fields[next++] = valueAlarm; + if(gotAlarm) {fields[next++] = alarmField; alarmField->incReferenceCount();} + if(gotTimeStamp) {fields[next++] = timeStampField; timeStampField->incReferenceCount();} + if(gotDisplay) {fields[next++] = displayField; displayField->incReferenceCount();} + if(gotControl) {fields[next++] = controlField; controlField->incReferenceCount();} + if(gotValueAlarm) {fields[next++] = valueAlarm; valueAlarm->incReferenceCount();} return fieldCreate->createStructure(fieldName,numFields,fields); } @@ -438,44 +443,74 @@ StructureConstPtr StandardField::enumeratedAlarm() void StandardField::init() { createAlarm(); - alarmField->incReferenceCount(); createTimeStamp(); - timeStampField->incReferenceCount(); createDisplay(); - displayField->incReferenceCount(); createControl(); - controlField->incReferenceCount(); createBooleanAlarm(); - booleanAlarmField->incReferenceCount(); createByteAlarm(); - byteAlarmField->incReferenceCount(); createShortAlarm(); - shortAlarmField->incReferenceCount(); createIntAlarm(); - intAlarmField->incReferenceCount(); createLongAlarm(); - longAlarmField->incReferenceCount(); createFloatAlarm(); - floatAlarmField->incReferenceCount(); createDoubleAlarm(); - doubleAlarmField->incReferenceCount(); createEnumeratedAlarm(); - enumeratedAlarmField->incReferenceCount(); } StandardField::StandardField(){init();} -StandardField::~StandardField(){} +StandardField::~StandardField(){ +} +static void myDeleteStatic() +{ + int count = alarmField->getReferenceCount(); + if(count!=1) printf("~StandardField() alarmField reference count %d\n",count); + alarmField->decReferenceCount(); + count = timeStampField->getReferenceCount(); + if(count!=1) printf("~StandardField() timeStampField reference count %d\n",count); + timeStampField->decReferenceCount(); + count = displayField->getReferenceCount(); + if(count!=1) printf("~StandardField() displayField reference count %d\n",count); + displayField->decReferenceCount(); + count = controlField->getReferenceCount(); + if(count!=1) printf("~StandardField() controlField reference count %d\n",count); + controlField->decReferenceCount(); + count = booleanAlarmField->getReferenceCount(); + if(count!=1) printf("~StandardField() booleanAlarmField reference count %d\n",count); + booleanAlarmField->decReferenceCount(); + count = byteAlarmField->getReferenceCount(); + if(count!=1) printf("~StandardField() byteAlarmField reference count %d\n",count); + byteAlarmField->decReferenceCount(); + count = shortAlarmField->getReferenceCount(); + if(count!=1) printf("~StandardField() shortAlarmField reference count %d\n",count); + shortAlarmField->decReferenceCount(); + count = intAlarmField->getReferenceCount(); + if(count!=1) printf("~StandardField() intAlarmField reference count %d\n",count); + intAlarmField->decReferenceCount(); + count = longAlarmField->getReferenceCount(); + if(count!=1) printf("~StandardField() longAlarmField reference count %d\n",count); + longAlarmField->decReferenceCount(); + count = floatAlarmField->getReferenceCount(); + if(count!=1) printf("~StandardField() floatAlarmField reference count %d\n",count); + floatAlarmField->decReferenceCount(); + count = doubleAlarmField->getReferenceCount(); + if(count!=1) printf("~StandardField() doubleAlarmField reference count %d\n",count); + doubleAlarmField->decReferenceCount(); + count = enumeratedAlarmField->getReferenceCount(); + if(count!=1) printf("~StandardField() enumeratedAlarmField reference count %d\n",count); + enumeratedAlarmField->decReferenceCount(); +} StandardField * getStandardField() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - - if(standardField==0) { + Lock xx(&globalMutex); + if(notInited) { + notInited = false; standardField = new StandardField(); fieldCreate = getFieldCreate(); + ShowConstructDestruct::registerCallback( + "standardField", + 0,0,0,myDeleteStatic); } return standardField; } diff --git a/pvDataApp/factory/StandardPVField.cpp b/pvDataApp/factory/StandardPVField.cpp index d8b1268..a24cb20 100644 --- a/pvDataApp/factory/StandardPVField.cpp +++ b/pvDataApp/factory/StandardPVField.cpp @@ -12,13 +12,17 @@ #include "convert.h" #include "standardField.h" #include "standardPVField.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { +static Mutex globalMutex; +static bool notInited = true; +static StandardField *standardField = 0; + static String notImplemented("not implemented"); static FieldCreate* fieldCreate = 0; static PVDataCreate* pvDataCreate = 0; -static StandardField *standardField = 0; static StandardPVField *standardPVField = 0; static void addExtendsStructureName(PVStructure *pvStructure,String properties) @@ -325,15 +329,22 @@ public: StandardPVFieldExt(): StandardPVField(){}; }; -StandardPVField * getStandardPVField() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); +static void myDeleteStatic() +{ + delete standardPVField; +} - if(standardPVField==0) { +StandardPVField * getStandardPVField() { + Lock xx(&globalMutex); + if(notInited) { + notInited = false; fieldCreate = getFieldCreate(); pvDataCreate = getPVDataCreate(); standardField = getStandardField(); standardPVField = new StandardPVFieldExt(); + ShowConstructDestruct::registerCallback( + "standardPVField", + 0,0,0,myDeleteStatic); } return standardPVField; } diff --git a/pvDataApp/misc/StatusCreateFactory.cpp b/pvDataApp/misc/StatusCreateFactory.cpp index 5e308d3..86e9f4c 100644 --- a/pvDataApp/misc/StatusCreateFactory.cpp +++ b/pvDataApp/misc/StatusCreateFactory.cpp @@ -21,31 +21,29 @@ namespace epics { namespace pvData { static volatile int64 totalConstruct = 0; static volatile int64 totalDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; static int64 getTotalConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalConstruct; } static int64 getTotalDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalDestruct; } -static ConstructDestructCallback *pConstructDestructCallback; - static void init() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pConstructDestructCallback = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( String("status"), - getTotalConstruct,getTotalDestruct,0); + getTotalConstruct,getTotalDestruct,0,0); } } @@ -56,19 +54,19 @@ class StatusImpl : public Status StatusImpl(StatusType type, String message) : m_type(type), m_message(message) { - Lock xx(globalMutex); + Lock xx(&globalMutex); totalConstruct++; } StatusImpl(StatusType type, String message, String stackDump) : m_type(type), m_message(message), m_stackDump(stackDump) { - Lock xx(globalMutex); + Lock xx(&globalMutex); totalConstruct++; } virtual ~StatusImpl() { - Lock xx(globalMutex); + Lock xx(&globalMutex); totalDestruct++; } @@ -207,7 +205,7 @@ class StatusCreateImpl : public StatusCreate { static StatusCreate* statusCreate = 0; StatusCreate* getStatusCreate() { - static Mutex mutex = Mutex(); + static Mutex mutex; Lock xx(&mutex); if(statusCreate==0) statusCreate = new StatusCreateImpl(); diff --git a/pvDataApp/misc/bitSet.cpp b/pvDataApp/misc/bitSet.cpp index 70e0e40..fe0b620 100644 --- a/pvDataApp/misc/bitSet.cpp +++ b/pvDataApp/misc/bitSet.cpp @@ -8,38 +8,38 @@ #include "stdio.h" #include "bitSet.h" #include "lock.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { - + //static DebugLevel debugLevel = lowDebug; - + + static Mutex globalMutex; + static volatile int64 totalConstruct = 0; static volatile int64 totalDestruct = 0; - static Mutex *globalMutex = 0; + static bool notInited = true; static int64 getTotalConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalConstruct; } static int64 getTotalDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalDestruct; } - static ConstructDestructCallback *pConstructDestructCallback; - static void init() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pConstructDestructCallback = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( String("bitSet"), - getTotalConstruct,getTotalDestruct,0); + getTotalConstruct,getTotalDestruct,0,0); } } @@ -47,7 +47,7 @@ namespace epics { namespace pvData { initWords(BITS_PER_WORD); init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalConstruct++; } @@ -55,14 +55,14 @@ namespace epics { namespace pvData { initWords(nbits); init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalConstruct++; } BitSet::~BitSet() { delete[] words; - Lock xx(globalMutex); + Lock xx(&globalMutex); totalDestruct++; } diff --git a/pvDataApp/misc/bitSet.h b/pvDataApp/misc/bitSet.h index 982f5f3..8d5bebb 100644 --- a/pvDataApp/misc/bitSet.h +++ b/pvDataApp/misc/bitSet.h @@ -9,7 +9,6 @@ #include #include #include "factory.h" -#include "showConstructDestruct.h" //#include "byteBuffer.h" //#include "serialize.h" namespace epics { namespace pvData { diff --git a/pvDataApp/misc/event.cpp b/pvDataApp/misc/event.cpp index ea0b4f1..52b5fa3 100644 --- a/pvDataApp/misc/event.cpp +++ b/pvDataApp/misc/event.cpp @@ -20,45 +20,44 @@ #include "pvType.h" #include "lock.h" #include "event.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { +static Mutex globalMutex; static volatile int64 totalConstruct = 0; static volatile int64 totalDestruct = 0; -static Mutex *globalMutex = 0; +static bool notInited = true; static String alreadyOn("already on list"); static int64 getTotalConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalConstruct; } static int64 getTotalDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalDestruct; } -static ConstructDestructCallback *pConstructDestructCallback; - static void init() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pConstructDestructCallback = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( String("event"), - getTotalConstruct,getTotalDestruct,0); + getTotalConstruct,getTotalDestruct,0,0); } -} +} Event::~Event() { epicsEventDestroy(id); id = 0; - Lock xx(globalMutex); + Lock xx(&globalMutex); totalDestruct++; } @@ -67,16 +66,10 @@ Event::Event(bool full) : id(epicsEventCreate(full?epicsEventFull : epicsEventEmpty)) { init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalConstruct++; } -ConstructDestructCallback *Event::getConstructDestructCallback() -{ - init(); - return pConstructDestructCallback; -} - void Event::signal() { if(id==0) throw std::logic_error(String("event was deleted")); diff --git a/pvDataApp/misc/event.h b/pvDataApp/misc/event.h index 00dcdb0..5ca6a75 100644 --- a/pvDataApp/misc/event.h +++ b/pvDataApp/misc/event.h @@ -8,11 +8,9 @@ #define EVENT_H #include #include -#include #include #include "noDefaultMethods.h" #include "pvType.h" -#include "showConstructDestruct.h" namespace epics { namespace pvData { @@ -20,7 +18,6 @@ class Event : private NoDefaultMethods { public: explicit Event(bool = false); ~Event(); - static ConstructDestructCallback *getConstructDestructCallback(); void signal(); bool wait (); /* blocks until full */ bool wait ( double timeOut ); /* false if empty at time out */ diff --git a/pvDataApp/misc/executor.cpp b/pvDataApp/misc/executor.cpp index bb96898..7ec1e04 100644 --- a/pvDataApp/misc/executor.cpp +++ b/pvDataApp/misc/executor.cpp @@ -17,35 +17,34 @@ #include "thread.h" #include "event.h" #include "executor.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { static volatile int64 totalConstruct = 0; static volatile int64 totalDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; static int64 getTotalConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalConstruct; } static int64 getTotalDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalDestruct; } -static ConstructDestructCallback *pConstructDestructCallback; - static void init() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pConstructDestructCallback = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( String("executor"), - getTotalConstruct,getTotalDestruct,0); + getTotalConstruct,getTotalDestruct,0,0); } } @@ -75,12 +74,6 @@ ExecutorNode::~ExecutorNode() delete runNode; } -ConstructDestructCallback *Executor::getConstructDestructCallback() -{ - init(); - return pConstructDestructCallback; -} - class ExecutorPvt : public Runnable{ public: ExecutorPvt(String threadName,ThreadPriority priority); @@ -169,13 +162,13 @@ Executor::Executor(String threadName,ThreadPriority priority) : pImpl(new ExecutorPvt(threadName,priority)) { init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalConstruct++; } Executor::~Executor() { delete pImpl; - Lock xx(globalMutex); + Lock xx(&globalMutex); totalDestruct++; } diff --git a/pvDataApp/misc/executor.h b/pvDataApp/misc/executor.h index 1c70439..ebbe0c2 100644 --- a/pvDataApp/misc/executor.h +++ b/pvDataApp/misc/executor.h @@ -26,7 +26,6 @@ class Executor : private NoDefaultMethods { public: Executor(String threadName,ThreadPriority priority); ~Executor(); - static ConstructDestructCallback *getConstructDestructCallback(); ExecutorNode * createNode(Command *command); void execute(ExecutorNode *node); private: diff --git a/pvDataApp/misc/linkedListVoid.cpp b/pvDataApp/misc/linkedListVoid.cpp index 097b3a4..7b1d6e4 100644 --- a/pvDataApp/misc/linkedListVoid.cpp +++ b/pvDataApp/misc/linkedListVoid.cpp @@ -14,56 +14,55 @@ #include "lock.h" #include "pvType.h" #include "linkedListVoid.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { +static Mutex globalMutex; +static String alreadyOnList("already on list"); + static volatile int64 totalNodeConstruct = 0; static volatile int64 totalNodeDestruct = 0; static volatile int64 totalListConstruct = 0; static volatile int64 totalListDestruct = 0; -static Mutex *globalMutex = 0; -static String alreadyOnList("already on list"); +static bool notInited = true; static int64 getTotalNodeConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalNodeConstruct; } static int64 getTotalNodeDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalNodeDestruct; } static int64 getTotalListConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalListConstruct; } static int64 getTotalListDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalListDestruct; } -static ConstructDestructCallback *pCDCallbackLinkedListNode; -static ConstructDestructCallback *pCDCallbackLinkedList; - static void initPvt() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pCDCallbackLinkedListNode = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( "linkedListNode", - getTotalNodeConstruct,getTotalNodeDestruct,0); + getTotalNodeConstruct,getTotalNodeDestruct,0,0); - pCDCallbackLinkedList = new ConstructDestructCallback( + ShowConstructDestruct::registerCallback( "linkedList", - getTotalListConstruct,getTotalListDestruct,0); + getTotalListConstruct,getTotalListDestruct,0,0); } } @@ -72,7 +71,7 @@ LinkedListVoidNode::LinkedListVoidNode(void *object) : object(object),before(0),after(0),linkedListVoid(0) { initPvt(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalNodeConstruct++; } @@ -80,23 +79,17 @@ LinkedListVoidNode::LinkedListVoidNode(bool isHead) : object(this),before(this),after(this) { initPvt(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalNodeConstruct++; } LinkedListVoidNode::~LinkedListVoidNode() { - Lock xx(globalMutex); + Lock xx(&globalMutex); totalNodeDestruct++; } -ConstructDestructCallback *LinkedListVoidNode::getConstructDestructCallback() -{ - initPvt(); - return pCDCallbackLinkedListNode; -} - void *LinkedListVoidNode::getObject() { return object; } @@ -111,23 +104,17 @@ LinkedListVoid::LinkedListVoid() : head(new LinkedListVoidNode(true)),length(0) { initPvt(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalListConstruct++; } LinkedListVoid::~LinkedListVoid() { - Lock xx(globalMutex); + Lock xx(&globalMutex); delete head; totalListDestruct++; } -ConstructDestructCallback *LinkedListVoid::getConstructDestructCallback() -{ - initPvt(); - return pCDCallbackLinkedList; -} - int LinkedListVoid::getLength() { return length; diff --git a/pvDataApp/misc/linkedListVoid.h b/pvDataApp/misc/linkedListVoid.h index d19c648..fa7d34c 100644 --- a/pvDataApp/misc/linkedListVoid.h +++ b/pvDataApp/misc/linkedListVoid.h @@ -6,7 +6,6 @@ */ #include "pvType.h" -#include "showConstructDestruct.h" #ifndef LINKEDLISTVOID_H #define LINKEDLISTVOID_H namespace epics { namespace pvData { @@ -17,7 +16,6 @@ class LinkedListVoidNode; class LinkedListVoidNode { public: ~LinkedListVoidNode(); - static ConstructDestructCallback *getConstructDestructCallback(); void *getObject(); bool isOnList(); protected: @@ -37,7 +35,6 @@ private: class LinkedListVoid { public: ~LinkedListVoid(); - static ConstructDestructCallback *getConstructDestructCallback(); int getLength(); void addTail(LinkedListVoidNode *listNode); void addHead(LinkedListVoidNode *listNode); diff --git a/pvDataApp/misc/messageQueue.cpp b/pvDataApp/misc/messageQueue.cpp index 5743914..eea6deb 100644 --- a/pvDataApp/misc/messageQueue.cpp +++ b/pvDataApp/misc/messageQueue.cpp @@ -23,31 +23,29 @@ namespace epics { namespace pvData { static volatile int64 totalQueueConstruct = 0; static volatile int64 totalQueueDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; static int64 getTotalQueueConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalQueueConstruct; } static int64 getTotalQueueDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalQueueDestruct; } -static ConstructDestructCallback *pCDCallbackQueue; - static void initPvt() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pCDCallbackQueue = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( "messageQueue", - getTotalQueueConstruct,getTotalQueueDestruct,0); + getTotalQueueConstruct,getTotalQueueDestruct,0,0); } } @@ -60,7 +58,8 @@ typedef Queue MessageNodeQueue; MessageNode::MessageNode() : message(String("")),messageType(infoMessage){} -MessageNode::~MessageNode() {} +MessageNode::~MessageNode() { +} String MessageNode::getMessage() const { return message;}; @@ -81,7 +80,7 @@ MessageQueue::MessageQueue(int size) : pImpl(new MessageQueuePvt) { initPvt(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalQueueConstruct++; pImpl->size = size; pImpl->overrun = 0; @@ -101,8 +100,7 @@ MessageQueue::~MessageQueue() delete pImpl->messageNodeArray[i]; } delete[] pImpl->messageNodeArray; - initPvt(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalQueueDestruct++; } diff --git a/pvDataApp/misc/messageQueue.h b/pvDataApp/misc/messageQueue.h index b029afe..fe0214d 100644 --- a/pvDataApp/misc/messageQueue.h +++ b/pvDataApp/misc/messageQueue.h @@ -9,7 +9,6 @@ #include "pvType.h" #include "requester.h" #include "noDefaultMethods.h" -#include "showConstructDestruct.h" namespace epics { namespace pvData { @@ -29,7 +28,6 @@ class MessageQueue : private NoDefaultMethods { public: MessageQueue(int size); ~MessageQueue(); - static ConstructDestructCallback *getConstructDestructCallback(); MessageNode *get(); // must call release before next get void release(); diff --git a/pvDataApp/misc/queueVoid.cpp b/pvDataApp/misc/queueVoid.cpp index a33257e..c8274eb 100644 --- a/pvDataApp/misc/queueVoid.cpp +++ b/pvDataApp/misc/queueVoid.cpp @@ -14,6 +14,7 @@ #include "lock.h" #include "pvType.h" #include "queueVoid.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { @@ -21,48 +22,44 @@ static volatile int64 totalElementConstruct = 0; static volatile int64 totalElementDestruct = 0; static volatile int64 totalQueueConstruct = 0; static volatile int64 totalQueueDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; static int64 getTotalNodeConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalElementConstruct; } static int64 getTotalNodeDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalElementDestruct; } static int64 getTotalListConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalQueueConstruct; } static int64 getTotalListDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalQueueDestruct; } -static ConstructDestructCallback *pCDCallbackQueueNode; -static ConstructDestructCallback *pCDCallbackQueue; - static void initPvt() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pCDCallbackQueueNode = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( "queueElement", - getTotalNodeConstruct,getTotalNodeDestruct,0); - - pCDCallbackQueue = new ConstructDestructCallback( + getTotalNodeConstruct,getTotalNodeDestruct,0,0); + ShowConstructDestruct::registerCallback( "queue", - getTotalListConstruct,getTotalListDestruct,0); + getTotalListConstruct,getTotalListDestruct,0,0); } } @@ -71,23 +68,17 @@ QueueElementVoid::QueueElementVoid(ObjectPtr object) : object(object) { initPvt(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalElementConstruct++; } QueueElementVoid::~QueueElementVoid() { - Lock xx(globalMutex); + Lock xx(&globalMutex); totalElementDestruct++; } -ConstructDestructCallback *QueueElementVoid::getConstructDestructCallback() -{ - initPvt(); - return pCDCallbackQueueNode; -} - ObjectPtr QueueElementVoid::getObject() { return object; } @@ -104,7 +95,7 @@ QueueVoid::QueueVoid(ObjectPtr object[],int number) array[i] = new QueueElementVoid(object[i]); } initPvt(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalQueueConstruct++; } @@ -114,16 +105,10 @@ QueueVoid::~QueueVoid() delete array[i]; } delete[]array; - Lock xx(globalMutex); + Lock xx(&globalMutex); totalQueueDestruct++; } -ConstructDestructCallback *QueueVoid::getConstructDestructCallback() -{ - initPvt(); - return pCDCallbackQueue; -} - void QueueVoid::clear() { numberFree = number; diff --git a/pvDataApp/misc/queueVoid.h b/pvDataApp/misc/queueVoid.h index 559f932..6a85dcf 100644 --- a/pvDataApp/misc/queueVoid.h +++ b/pvDataApp/misc/queueVoid.h @@ -4,7 +4,6 @@ * EPICS pvDataCPP is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ -#include "showConstructDestruct.h" #ifndef QUEUEVOID_H #define QUEUEVOID_H namespace epics { namespace pvData { @@ -17,8 +16,6 @@ typedef QueueElementVoid * QueueElementVoidPtr; typedef QueueElementVoidPtr * QueueElementVoidPtrArray; class QueueElementVoid { -public: - static ConstructDestructCallback *getConstructDestructCallback(); protected: ObjectPtr getObject(); QueueElementVoid(ObjectPtr object); @@ -29,8 +26,6 @@ protected: class QueueVoid { -public: - static ConstructDestructCallback *getConstructDestructCallback(); protected: QueueVoid(ObjectPtr array[],int number); ~QueueVoid(); diff --git a/pvDataApp/misc/showConstructDestruct.cpp b/pvDataApp/misc/showConstructDestruct.cpp index c6f6c61..d62e381 100644 --- a/pvDataApp/misc/showConstructDestruct.cpp +++ b/pvDataApp/misc/showConstructDestruct.cpp @@ -20,20 +20,28 @@ namespace epics { namespace pvData { static ShowConstructDestruct *pShowConstructDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; typedef LinkedListNode ListNode; typedef LinkedList List; static List *list; +/* list callbacks are special because showConstructDestruct creates a list + Thus list can be null when list calls registerCallback + The list callbacks are not put on the list but handled separately + */ +static ConstructDestructCallback *listCallback = 0; +static ConstructDestructCallback *listNodeCallback = 0; + ConstructDestructCallback::ConstructDestructCallback( String name, - getTotal construct, - getTotal destruct, - getTotal reference) -: name(name), construct(construct), destruct(destruct) ,reference(reference) -{ - getShowConstructDestruct()->registerCallback(this); -} + getTotalFunc construct, + getTotalFunc destruct, + getTotalFunc reference, + deleteStaticFunc deleteFunc) +: name(name), construct(construct), destruct(destruct) ,reference(reference), + deleteFunc(deleteFunc) +{ } ConstructDestructCallback::~ConstructDestructCallback() {} @@ -44,11 +52,13 @@ String ConstructDestructCallback::getConstructName() int64 ConstructDestructCallback::getTotalConstruct() { + if(construct==0) return 0; return construct(); } int64 ConstructDestructCallback:: getTotalDestruct() { + if(destruct==0) return 0; return destruct(); } @@ -58,68 +68,142 @@ int64 ConstructDestructCallback::getTotalReferenceCount() return reference(); } +void ConstructDestructCallback::deleteStatic() +{ + if(deleteFunc==0) return; + deleteFunc(); +} ShowConstructDestruct::ShowConstructDestruct() {} +ShowConstructDestruct::~ShowConstructDestruct() { + delete listCallback; + delete listNodeCallback; + listCallback = 0; + listNodeCallback = 0; +} + +void ShowConstructDestruct::registerCallback( + String name, + getTotalFunc construct, + getTotalFunc destruct, + getTotalFunc reference, + deleteStaticFunc deleteFunc) +{ + getShowConstructDestruct(); // make it initialize + Lock xx(&globalMutex); + if(name.compare("linkedList")==0) { + listCallback = new ConstructDestructCallback( + name,construct,destruct,reference,deleteFunc); + return; + } else if(name.compare("linkedListNode")==0) { + listNodeCallback = new ConstructDestructCallback( + name,construct,destruct,reference,deleteFunc); + return; + } + if(list==0) { + throw std::logic_error(String( + "ShowConstructDestruct::registerCallback")); + } + ConstructDestructCallback *callback = new ConstructDestructCallback( + name,construct,destruct,reference,deleteFunc); + ListNode *listNode = new ListNode(callback); + list->addTail(listNode); +} +static void showOne(ConstructDestructCallback *callback,FILE *fd) +{ + String name = callback->getConstructName(); + int64 reference = callback->getTotalReferenceCount(); + int64 construct = callback->getTotalConstruct(); + int64 destruct = callback->getTotalDestruct(); + if(reference==0&&construct==0&&destruct==0) return; + fprintf(fd,"%s: ", name.c_str()); + if(construct>0 || destruct>0) { + fprintf(fd," totalConstruct %lli totalDestruct %lli", + construct,destruct); + } + if(reference>0) fprintf(fd," totalReference %lli",reference); + int64 diff = construct - destruct; + if(diff!=0) fprintf(fd," ACTIVE %lli",diff); + fprintf(fd,"\n"); +} + +ConstructDestructCallback* ShowConstructDestruct::getConstructDestructCallback( + String name) +{ + if(name.compare(listNodeCallback->getConstructName())==0) { + return listNodeCallback; + } + if(name.compare(listCallback->getConstructName())==0) { + return listCallback; + } + Lock xx(&globalMutex); + ListNode *node = list->getHead(); + while(node!=0) { + ConstructDestructCallback *callback = node->getObject(); + if(name.compare(callback->getConstructName())==0) { + return callback; + } + node = list->getNext(node); + } + return 0; +} + void ShowConstructDestruct::constuctDestructTotals(FILE *fd) { getShowConstructDestruct(); // make it initialize - Lock xx(globalMutex); + Lock xx(&globalMutex); ListNode *node = list->getHead(); while(node!=0) { ConstructDestructCallback *callback = node->getObject(); - String name = callback->getConstructName(); - int64 reference = callback->getTotalReferenceCount(); - int64 construct = callback->getTotalConstruct(); - int64 destruct = callback->getTotalDestruct(); - fprintf(fd,"%s: totalConstruct %lli totalDestruct %lli", - name.c_str(),construct,destruct); - if(reference>0) fprintf(fd," totalReference %lli",reference); - fprintf(fd,"\n"); + showOne(callback,fd); node = list->getNext(node); } + showOne(listNodeCallback,fd); + showOne(listCallback,fd); } -void ShowConstructDestruct::registerCallback(ConstructDestructCallback *callback) +void ShowConstructDestruct::showDeleteStaticExit(FILE *fd) { - static ConstructDestructCallback *listCallback = 0; - static ConstructDestructCallback *listNodeCallback = 0; - Lock xx(globalMutex); - ListNode *listNode = 0; - if(list==0) { - if(callback->getConstructName().compare("linkedListNode")==0) { - listNodeCallback = callback; - } else if(callback->getConstructName().compare("linkedList")==0) { - listCallback = callback; - } else { - throw std::logic_error(String("ShowConstructDestruct::registerCallback")); - } - return; - } - if(listCallback!=0) { - if(listNodeCallback==0) { - throw std::logic_error(String( - "ShowConstructDestruct::registerCallback expected listNodeCallback!=0")); - } - listNode = new ListNode(listNodeCallback); - list->addTail(listNode); - listNode = new ListNode(listCallback); - list->addTail(listNode); - listCallback = 0; - listNodeCallback = 0; - } - listNode = new ListNode(callback); - list->addTail(listNode); + getShowConstructDestruct(); // make it initialize + { + Lock xx(&globalMutex); + ListNode *node = list->getHead(); + while(node!=0) { + ConstructDestructCallback *callback = node->getObject(); + if(callback->deleteFunc!=0) callback->deleteFunc(); + node = list->getNext(node); + } + node = list->getHead(); + while(node!=0) { + ConstructDestructCallback *callback = node->getObject(); + showOne(callback,fd); + list->removeHead(); + delete callback; + delete node; + node = list->getHead(); + } + delete list; + if(listNodeCallback->deleteFunc!=0) listNodeCallback->deleteFunc(); + if(listCallback->deleteFunc!=0) listCallback->deleteFunc(); + showOne(listNodeCallback,fd); + showOne(listCallback,fd); + delete pShowConstructDestruct; + pShowConstructDestruct = 0; + } + exit( 0); } ShowConstructDestruct * getShowConstructDestruct() { - static Mutex mutex = Mutex(); + static Mutex mutex; Lock xx(&mutex); - if(pShowConstructDestruct==0) { - globalMutex = new Mutex(); + if(notInited) { + notInited = false; pShowConstructDestruct = new ShowConstructDestruct(); - list = new List(); + List *listTemp; + listTemp = new List(); + list = listTemp; } return pShowConstructDestruct; } diff --git a/pvDataApp/misc/showConstructDestruct.h b/pvDataApp/misc/showConstructDestruct.h index e41daa1..b8e1973 100644 --- a/pvDataApp/misc/showConstructDestruct.h +++ b/pvDataApp/misc/showConstructDestruct.h @@ -17,33 +17,46 @@ namespace epics { namespace pvData { -typedef int64 (*getTotal)(); +typedef int64 (*getTotalFunc)(); +typedef void (*deleteStaticFunc)(); class ConstructDestructCallback : private NoDefaultMethods { public: - ConstructDestructCallback( - String name, - getTotal construct, - getTotal destruct, - getTotal reference); String getConstructName(); int64 getTotalConstruct(); int64 getTotalDestruct(); int64 getTotalReferenceCount(); private: + ConstructDestructCallback( + String name, + getTotalFunc construct, + getTotalFunc destruct, + getTotalFunc reference, + deleteStaticFunc deleteFunc); ~ConstructDestructCallback(); + void deleteStatic(); String name; - getTotal construct; - getTotal destruct; - getTotal reference; + getTotalFunc construct; + getTotalFunc destruct; + getTotalFunc reference; + deleteStaticFunc deleteFunc; + friend class ShowConstructDestruct; }; class ShowConstructDestruct : private NoDefaultMethods { public: + static void registerCallback( + String name, + getTotalFunc construct, + getTotalFunc destruct, + getTotalFunc reference, + deleteStaticFunc deleteFunc); + ConstructDestructCallback* getConstructDestructCallback(String name); void constuctDestructTotals(FILE *fd); - void registerCallback(ConstructDestructCallback *callback); + static void showDeleteStaticExit(FILE *fd); private: ShowConstructDestruct(); + ~ShowConstructDestruct(); friend ShowConstructDestruct* getShowConstructDestruct(); }; @@ -56,41 +69,39 @@ extern ShowConstructDestruct* getShowConstructDestruct(); #define PVDATA_REFCOUNT_MONITOR_DEFINE(NAME) \ static volatile int64 NAME ## _totalConstruct = 0; \ static volatile int64 NAME ## _totalDestruct = 0; \ - static Mutex * NAME ## _globalMutex = 0; \ + static Mutex globalMutex; \ \ + static bool notInited = true; \ static int64 NAME ## _processTotalConstruct() \ { \ - Lock xx(NAME ## _globalMutex); \ + Lock xx(&globalMutex); \ return NAME ## _totalConstruct; \ } \ \ static int64 NAME ## _processTotalDestruct() \ { \ - Lock xx(NAME ## _globalMutex); \ + Lock xx(&globalMutex); \ return NAME ## _totalDestruct; \ } \ \ - static ConstructDestructCallback * NAME ## _pConstructDestructCallback; \ - \ static void NAME ## _init() \ { \ - static Mutex mutex = Mutex(); \ - Lock xx(&mutex); \ - if(NAME ## _globalMutex==0) { \ - NAME ## _globalMutex = new Mutex(); \ - NAME ## _pConstructDestructCallback = new ConstructDestructCallback( \ - String(#NAME), \ + Lock xx(&globalMutex); \ + if(notInited) { \ + notInited = false; \ + ShowConstructDestruct::registerCallback( \ + String("#NAME"), \ NAME ## _processTotalConstruct,NAME ## _processTotalDestruct,0); \ } \ } #define PVDATA_REFCOUNT_MONITOR_DESTRUCT(NAME) \ - Lock xx(NAME ## _globalMutex); \ + Lock xx(&globalMutex); \ NAME ## _totalDestruct++; #define PVDATA_REFCOUNT_MONITOR_CONSTRUCT(NAME) \ NAME ## _init(); \ - Lock xx(NAME ## _globalMutex); \ + Lock xx(&globalMutex); \ NAME ## _totalConstruct++; diff --git a/pvDataApp/misc/thread.cpp b/pvDataApp/misc/thread.cpp index 5c0dbff..feb10b8 100644 --- a/pvDataApp/misc/thread.cpp +++ b/pvDataApp/misc/thread.cpp @@ -17,6 +17,7 @@ #include "event.h" #include "thread.h" #include "linkedList.h" +#include "showConstructDestruct.h" namespace epics { namespace pvData { @@ -48,33 +49,36 @@ typedef LinkedList ThreadList; static volatile int64 totalConstruct = 0; static volatile int64 totalDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; static ThreadList *threadList; static int64 getTotalConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalConstruct; } static int64 getTotalDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalDestruct; } -static ConstructDestructCallback *pConstructDestructCallback; +static void deleteStatic() +{ + delete threadList; +} static void init() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); + Lock xx(&globalMutex); + if(notInited) { + notInited = false; threadList = new ThreadList(); - pConstructDestructCallback = new ConstructDestructCallback( + ShowConstructDestruct::registerCallback( String("thread"), - getTotalConstruct,getTotalDestruct,0); + getTotalConstruct,getTotalDestruct,0,deleteStatic); } } @@ -133,7 +137,7 @@ ThreadPvt::ThreadPvt(Thread *thread,String name, myFunc,this)) { init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); threadList->addTail(threadListElement->node); totalConstruct++; } @@ -157,7 +161,7 @@ ThreadPvt::~ThreadPvt() threadList->remove(threadListElement->node); delete waitDone; delete threadListElement; - Lock xx(globalMutex); + Lock xx(&globalMutex); totalDestruct++; } @@ -171,12 +175,6 @@ Thread::~Thread() delete pImpl; } -ConstructDestructCallback *Thread::getConstructDestructCallback() -{ - init(); - return pConstructDestructCallback; -} - void Thread::sleep(double seconds) { epicsThreadSleep(seconds);; @@ -195,7 +193,7 @@ ThreadPriority Thread::getPriority() void Thread::showThreads(StringBuilder buf) { init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); ThreadListNode *node = threadList->getHead(); while(node!=0) { Thread *thread = node->getObject()->thread; diff --git a/pvDataApp/misc/thread.h b/pvDataApp/misc/thread.h index 664a20d..549bb79 100644 --- a/pvDataApp/misc/thread.h +++ b/pvDataApp/misc/thread.h @@ -8,7 +8,6 @@ #define THREAD_H #include "noDefaultMethods.h" #include "pvType.h" -#include "showConstructDestruct.h" namespace epics { namespace pvData { @@ -39,7 +38,6 @@ class Thread : private NoDefaultMethods { public: Thread(String name,ThreadPriority priority,Runnable *runnable); ~Thread(); - static ConstructDestructCallback *getConstructDestructCallback(); String getName(); ThreadPriority getPriority(); static void showThreads(StringBuilder buf); diff --git a/pvDataApp/misc/timer.cpp b/pvDataApp/misc/timer.cpp index 48231ec..9750246 100644 --- a/pvDataApp/misc/timer.cpp +++ b/pvDataApp/misc/timer.cpp @@ -28,63 +28,47 @@ static volatile int64 totalNodeConstruct = 0; static volatile int64 totalNodeDestruct = 0; static volatile int64 totalTimerConstruct = 0; static volatile int64 totalTimerDestruct = 0; -static Mutex *globalMutex = 0; +static Mutex globalMutex; +static bool notInited = true; static int64 getTotalTimerNodeConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalNodeConstruct; } static int64 getTotalTimerNodeDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalNodeDestruct; } static int64 getTotalTimerConstruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalTimerConstruct; } static int64 getTotalTimerDestruct() { - Lock xx(globalMutex); + Lock xx(&globalMutex); return totalTimerDestruct; } -static ConstructDestructCallback *pCDCallbackTimerNode; -static ConstructDestructCallback *pCDCallbackTimer; - static void init() { - static Mutex mutex = Mutex(); - Lock xx(&mutex); - if(globalMutex==0) { - globalMutex = new Mutex(); - pCDCallbackTimerNode = new ConstructDestructCallback( + Lock xx(&globalMutex); + if(notInited) { + notInited = false; + ShowConstructDestruct::registerCallback( "timerNode", - getTotalTimerNodeConstruct,getTotalTimerNodeDestruct,0); - - pCDCallbackTimer = new ConstructDestructCallback( + getTotalTimerNodeConstruct,getTotalTimerNodeDestruct,0,0); + ShowConstructDestruct::registerCallback( "timer", - getTotalTimerConstruct,getTotalTimerDestruct,0); + getTotalTimerConstruct,getTotalTimerDestruct,0,0); } } -ConstructDestructCallback * TimerNode::getConstructDestructCallback() -{ - init(); - return pCDCallbackTimerNode; -} - -ConstructDestructCallback * Timer::getConstructDestructCallback() -{ - init(); - return pCDCallbackTimer; -} - class TimerNodePvt; typedef LinkedListNode TimerListNode; @@ -171,7 +155,7 @@ TimerNode::TimerNode(TimerCallback *callback) : pImpl(new TimerNodePvt(this,callback)) { init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalNodeConstruct++; } @@ -180,7 +164,7 @@ TimerNode::~TimerNode() { cancel(); delete pImpl; - Lock xx(globalMutex); + Lock xx(&globalMutex); totalNodeDestruct++; } @@ -257,7 +241,7 @@ Timer::Timer(String threadName, ThreadPriority priority) : pImpl(new TimerPvt(threadName,priority)) { init(); - Lock xx(globalMutex); + Lock xx(&globalMutex); totalTimerConstruct++; } @@ -274,7 +258,7 @@ Timer::~Timer() { node->getObject()->callback->timerStopped(); } delete pImpl; - Lock xx(globalMutex); + Lock xx(&globalMutex); totalTimerDestruct++; } diff --git a/pvDataApp/misc/timer.h b/pvDataApp/misc/timer.h index 00f3e88..36fe4d8 100644 --- a/pvDataApp/misc/timer.h +++ b/pvDataApp/misc/timer.h @@ -15,7 +15,6 @@ #include "pvType.h" #include "thread.h" #include "noDefaultMethods.h" -#include "showConstructDestruct.h" namespace epics { namespace pvData { @@ -29,7 +28,6 @@ class TimerNode : private NoDefaultMethods { public: TimerNode(TimerCallback *timerCallback); ~TimerNode(); - static ConstructDestructCallback *getConstructDestructCallback(); void cancel(); bool isScheduled(); private: @@ -41,7 +39,6 @@ class Timer : private NoDefaultMethods { public: Timer(String threadName, ThreadPriority priority); ~Timer(); - static ConstructDestructCallback *getConstructDestructCallback(); void scheduleAfterDelay(TimerNode *timerNode,double delay); void schedulePeriodic(TimerNode *timerNode,double delay,double period); private: diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h index a1b56c8..4d2cb51 100644 --- a/pvDataApp/pv/pvData.h +++ b/pvDataApp/pv/pvData.h @@ -14,7 +14,6 @@ #include "requester.h" #include "byteBuffer.h" #include "serialize.h" -#include "showConstructDestruct.h" namespace epics { namespace pvData { class PVAuxInfo; @@ -63,7 +62,6 @@ class PVAuxInfo : private NoDefaultMethods { public: PVAuxInfo(PVField *pvField); ~PVAuxInfo(); - static ConstructDestructCallback *getConstructDestructCallback(); PVField * getPVField(); PVScalar * createInfo(String key,ScalarType scalarType); PVScalarMap getInfos(); @@ -87,7 +85,6 @@ class PVField { public: virtual ~PVField(); - static ConstructDestructCallback *getConstructDestructCallback(); String getRequesterName() ; virtual void message(String message,MessageType messageType) ; virtual void setRequester(Requester *prequester); diff --git a/pvDataApp/pv/pvIntrospect.h b/pvDataApp/pv/pvIntrospect.h index 4bfe30b..d54c762 100644 --- a/pvDataApp/pv/pvIntrospect.h +++ b/pvDataApp/pv/pvIntrospect.h @@ -10,7 +10,6 @@ #define PVINTROSPECT_H #include "noDefaultMethods.h" #include "pvType.h" -#include "showConstructDestruct.h" namespace epics { namespace pvData { class Field; @@ -60,7 +59,6 @@ public: class Field : private NoDefaultMethods { public: - static ConstructDestructCallback *getConstructDestructCallback(); int getReferenceCount() const; String getFieldName() const; Type getType() const; @@ -68,6 +66,7 @@ public: virtual void toString(StringBuilder buf,int indentLevel) const; void incReferenceCount() const; void decReferenceCount() const; + void dumpReferenceCount(StringBuilder buf,int indentLevel) const; virtual bool operator==(const Field& field) const; virtual bool operator!=(const Field& field) const; protected: diff --git a/test/testIntrospect b/test/testIntrospect index 41e60c8..9c5f4e7 100644 --- a/test/testIntrospect +++ b/test/testIntrospect @@ -77,7 +77,7 @@ structure value structure timeStamp long secondsPastEpoch int nanoSeconds -linkedListNode: totalConstruct 5 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -field: totalConstruct 156 totalDestruct 43 totalReference 169 -pvField: totalConstruct 55 totalDestruct 55 +field: totalConstruct 120 totalDestruct 120 +pvField: totalConstruct 47 totalDestruct 47 +linkedListNode: totalConstruct 4 totalDestruct 4 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testIntrospectDiff b/test/testIntrospectDiff index 9d85572..e69de29 100644 --- a/test/testIntrospectDiff +++ b/test/testIntrospectDiff @@ -1,4 +0,0 @@ -82c82 -< field: totalConstruct 156 totalDestruct 43 totalReference 169 ---- -> field: totalConstruct 156 totalDestruct 63 totalReference 93 diff --git a/test/testIntrospectGold b/test/testIntrospectGold index e5aba72..9c5f4e7 100644 --- a/test/testIntrospectGold +++ b/test/testIntrospectGold @@ -77,7 +77,7 @@ structure value structure timeStamp long secondsPastEpoch int nanoSeconds -linkedListNode: totalConstruct 5 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -field: totalConstruct 156 totalDestruct 63 totalReference 93 -pvField: totalConstruct 55 totalDestruct 55 +field: totalConstruct 120 totalDestruct 120 +pvField: totalConstruct 47 totalDestruct 47 +linkedListNode: totalConstruct 4 totalDestruct 4 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testLinkedList b/test/testLinkedList index be516b8..e149909 100644 --- a/test/testLinkedList +++ b/test/testLinkedList @@ -17,5 +17,5 @@ stack 4 3 2 1 0 Ordered Queue test list 0 1 2 3 4 -linkedListNode: totalConstruct 4041 totalDestruct 4038 -linkedList: totalConstruct 9 totalDestruct 8 +linkedListNode: totalConstruct 4039 totalDestruct 4039 +linkedList: totalConstruct 9 totalDestruct 9 diff --git a/test/testLinkedListAux b/test/testLinkedListAux index 2ded144..3216aaf 100644 --- a/test/testLinkedListAux +++ b/test/testLinkedListAux @@ -1,20 +1,20 @@ Time test -diff 27.074538 milliSeconds -time per iteration 27.074538 microseconds -time per addTail/removeHead 0.013537 microseconds +diff 23.623024 milliSeconds +time per iteration 23.623024 microseconds +time per addTail/removeHead 0.011812 microseconds Time test locked -diff 173.292669 milliSeconds -time per iteration 173.292669 microseconds -time per addTail/removeHead 0.086646 microseconds +diff 178.929120 milliSeconds +time per iteration 178.929120 microseconds +time per addTail/removeHead 0.089465 microseconds Time std::list test -diff 649.310063 milliSeconds -time per iteration 649.310063 microseconds -time per addTail/removeHead 0.324655 microseconds +diff 632.698846 milliSeconds +time per iteration 632.698846 microseconds +time per addTail/removeHead 0.316349 microseconds Time std::list test locked -diff 799.799680 milliSeconds -time per iteration 799.799680 microseconds -time per addTail/removeHead 0.399900 microseconds +diff 788.837800 milliSeconds +time per iteration 788.837800 microseconds +time per addTail/removeHead 0.394419 microseconds diff --git a/test/testLinkedListGold b/test/testLinkedListGold index be516b8..e149909 100644 --- a/test/testLinkedListGold +++ b/test/testLinkedListGold @@ -17,5 +17,5 @@ stack 4 3 2 1 0 Ordered Queue test list 0 1 2 3 4 -linkedListNode: totalConstruct 4041 totalDestruct 4038 -linkedList: totalConstruct 9 totalDestruct 8 +linkedListNode: totalConstruct 4039 totalDestruct 4039 +linkedList: totalConstruct 9 totalDestruct 9 diff --git a/test/testMessageQueue b/test/testMessageQueue index 2b51b75..36d38b1 100644 --- a/test/testMessageQueue +++ b/test/testMessageQueue @@ -1,5 +1,7 @@ -linkedListNode: totalConstruct 6 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -messageQueue: totalConstruct 1 totalDestruct 1 -queueElement: totalConstruct 3 totalDestruct 3 -queue: totalConstruct 1 totalDestruct 1 +message 1 messageType info +message 4 messageType info +messageQueue: totalConstruct 1 totalDestruct 1 +queueElement: totalConstruct 3 totalDestruct 3 +queue: totalConstruct 1 totalDestruct 1 +linkedListNode: totalConstruct 4 totalDestruct 4 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testMessageQueueAux b/test/testMessageQueueAux index 622297d..e69de29 100644 --- a/test/testMessageQueueAux +++ b/test/testMessageQueueAux @@ -1,2 +0,0 @@ -message 1 messageType info -message 4 messageType info diff --git a/test/testMessageQueueGold b/test/testMessageQueueGold index 2b51b75..36d38b1 100644 --- a/test/testMessageQueueGold +++ b/test/testMessageQueueGold @@ -1,5 +1,7 @@ -linkedListNode: totalConstruct 6 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -messageQueue: totalConstruct 1 totalDestruct 1 -queueElement: totalConstruct 3 totalDestruct 3 -queue: totalConstruct 1 totalDestruct 1 +message 1 messageType info +message 4 messageType info +messageQueue: totalConstruct 1 totalDestruct 1 +queueElement: totalConstruct 3 totalDestruct 3 +queue: totalConstruct 1 totalDestruct 1 +linkedListNode: totalConstruct 4 totalDestruct 4 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVAuxInfo b/test/testPVAuxInfo index a4580a8..37c78f5 100644 --- a/test/testPVAuxInfo +++ b/test/testPVAuxInfo @@ -33,8 +33,8 @@ units offset 11 next 12 number 1 limit offset 12 next 15 number 3 low offset 13 next 14 number 1 high offset 14 next 15 number 1 -linkedListNode: totalConstruct 6 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -field: totalConstruct 111 totalDestruct 12 totalReference 126 -pvField: totalConstruct 17 totalDestruct 17 -pvAuxInfo: totalConstruct 1 totalDestruct 1 +field: totalConstruct 97 totalDestruct 97 +pvField: totalConstruct 17 totalDestruct 17 +pvAuxInfo: totalConstruct 1 totalDestruct 1 +linkedListNode: totalConstruct 6 totalDestruct 6 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVAuxInfoDiff b/test/testPVAuxInfoDiff index 5538f12..e69de29 100644 --- a/test/testPVAuxInfoDiff +++ b/test/testPVAuxInfoDiff @@ -1,4 +0,0 @@ -38c38 -< field: totalConstruct 111 totalDestruct 12 totalReference 126 ---- -> field: totalConstruct 111 totalDestruct 18 totalReference 93 diff --git a/test/testPVAuxInfoGold b/test/testPVAuxInfoGold index 0ea79ff..37c78f5 100644 --- a/test/testPVAuxInfoGold +++ b/test/testPVAuxInfoGold @@ -33,8 +33,8 @@ units offset 11 next 12 number 1 limit offset 12 next 15 number 3 low offset 13 next 14 number 1 high offset 14 next 15 number 1 -linkedListNode: totalConstruct 6 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -field: totalConstruct 111 totalDestruct 18 totalReference 93 -pvField: totalConstruct 17 totalDestruct 17 -pvAuxInfo: totalConstruct 1 totalDestruct 1 +field: totalConstruct 97 totalDestruct 97 +pvField: totalConstruct 17 totalDestruct 17 +pvAuxInfo: totalConstruct 1 totalDestruct 1 +linkedListNode: totalConstruct 6 totalDestruct 6 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVData b/test/testPVData index 296be02..f415392 100644 --- a/test/testPVData +++ b/test/testPVData @@ -283,7 +283,7 @@ structure string timeStamp timeStamp long secondsPastEpoch 0 int nanoSeconds 0 -linkedListNode: totalConstruct 5 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -field: totalConstruct 391 totalDestruct 202 totalReference 443 -pvField: totalConstruct 281 totalDestruct 281 +field: totalConstruct 136 totalDestruct 136 +pvField: totalConstruct 281 totalDestruct 281 +linkedListNode: totalConstruct 5 totalDestruct 5 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVDataDiff b/test/testPVDataDiff index 045827d..e69de29 100644 --- a/test/testPVDataDiff +++ b/test/testPVDataDiff @@ -1,9 +0,0 @@ -1,2d0 -< structure request -< string fieldList value,timeStamp -288,289c286,287 -< field: totalConstruct 391 totalDestruct 202 totalReference 443 -< pvField: totalConstruct 281 totalDestruct 281 ---- -> field: totalConstruct 388 totalDestruct 295 totalReference 93 -> pvField: totalConstruct 279 totalDestruct 279 diff --git a/test/testPVDataGold b/test/testPVDataGold index 8199210..f415392 100644 --- a/test/testPVDataGold +++ b/test/testPVDataGold @@ -1,3 +1,5 @@ +structure request + string fieldList value,timeStamp testScalar boolean boolean true @@ -281,7 +283,7 @@ structure string timeStamp timeStamp long secondsPastEpoch 0 int nanoSeconds 0 -linkedListNode: totalConstruct 5 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -field: totalConstruct 388 totalDestruct 295 totalReference 93 -pvField: totalConstruct 279 totalDestruct 279 +field: totalConstruct 136 totalDestruct 136 +pvField: totalConstruct 281 totalDestruct 281 +linkedListNode: totalConstruct 5 totalDestruct 5 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVStructureArray b/test/testPVStructureArray index 606a864..9f04b50 100644 --- a/test/testPVStructureArray +++ b/test/testPVStructureArray @@ -54,7 +54,15 @@ structure powerSupply timeStamp timeStamp long secondsPastEpoch 0 int nanoSeconds 0 -linkedListNode: totalConstruct 5 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -field: totalConstruct 153 totalDestruct 31 totalReference 185 -pvField: totalConstruct 56 totalDestruct 56 + reference counts powerSupply referenceCount 1 + value referenceCount 1 + alarm referenceCount 14 + severity referenceCount 14 + message referenceCount 14 + timeStamp referenceCount 2 + secondsPastEpoch referenceCount 2 + nanoSeconds referenceCount 2 +field: totalConstruct 102 totalDestruct 102 +pvField: totalConstruct 56 totalDestruct 56 +linkedListNode: totalConstruct 5 totalDestruct 5 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testPVStructureArrayDiff b/test/testPVStructureArrayDiff index c6a4c4b..e69de29 100644 --- a/test/testPVStructureArrayDiff +++ b/test/testPVStructureArrayDiff @@ -1,4 +0,0 @@ -59c59 -< field: totalConstruct 153 totalDestruct 31 totalReference 185 ---- -> field: totalConstruct 153 totalDestruct 60 totalReference 93 diff --git a/test/testPVStructureArrayGold b/test/testPVStructureArrayGold index 3e016bb..9f04b50 100644 --- a/test/testPVStructureArrayGold +++ b/test/testPVStructureArrayGold @@ -54,7 +54,15 @@ structure powerSupply timeStamp timeStamp long secondsPastEpoch 0 int nanoSeconds 0 -linkedListNode: totalConstruct 5 totalDestruct 0 -linkedList: totalConstruct 1 totalDestruct 0 -field: totalConstruct 153 totalDestruct 60 totalReference 93 -pvField: totalConstruct 56 totalDestruct 56 + reference counts powerSupply referenceCount 1 + value referenceCount 1 + alarm referenceCount 14 + severity referenceCount 14 + message referenceCount 14 + timeStamp referenceCount 2 + secondsPastEpoch referenceCount 2 + nanoSeconds referenceCount 2 +field: totalConstruct 102 totalDestruct 102 +pvField: totalConstruct 56 totalDestruct 56 +linkedListNode: totalConstruct 5 totalDestruct 5 +linkedList: totalConstruct 1 totalDestruct 1 diff --git a/test/testQueue b/test/testQueue index 5764de8..0b0f26d 100644 --- a/test/testQueue +++ b/test/testQueue @@ -1,6 +1,6 @@ -linkedListNode: totalConstruct 9 totalDestruct 1 -linkedList: totalConstruct 2 totalDestruct 0 -queueElement: totalConstruct 5 totalDestruct 5 -queue: totalConstruct 1 totalDestruct 1 -event: totalConstruct 5 totalDestruct 5 -thread: totalConstruct 1 totalDestruct 1 +queueElement: totalConstruct 5 totalDestruct 5 +queue: totalConstruct 1 totalDestruct 1 +event: totalConstruct 5 totalDestruct 5 +thread: totalConstruct 1 totalDestruct 1 +linkedListNode: totalConstruct 7 totalDestruct 7 +linkedList: totalConstruct 2 totalDestruct 2 diff --git a/test/testQueueGold b/test/testQueueGold index 5764de8..0b0f26d 100644 --- a/test/testQueueGold +++ b/test/testQueueGold @@ -1,6 +1,6 @@ -linkedListNode: totalConstruct 9 totalDestruct 1 -linkedList: totalConstruct 2 totalDestruct 0 -queueElement: totalConstruct 5 totalDestruct 5 -queue: totalConstruct 1 totalDestruct 1 -event: totalConstruct 5 totalDestruct 5 -thread: totalConstruct 1 totalDestruct 1 +queueElement: totalConstruct 5 totalDestruct 5 +queue: totalConstruct 1 totalDestruct 1 +event: totalConstruct 5 totalDestruct 5 +thread: totalConstruct 1 totalDestruct 1 +linkedListNode: totalConstruct 7 totalDestruct 7 +linkedList: totalConstruct 2 totalDestruct 2 diff --git a/test/testThread b/test/testThread index 3e1887a..8766374 100644 --- a/test/testThread +++ b/test/testThread @@ -1,8 +1,8 @@ threads basic middle -linkedListNode: totalConstruct 17 totalDestruct 10 -linkedList: totalConstruct 6 totalDestruct 4 -event: totalConstruct 8 totalDestruct 8 -thread: totalConstruct 2 totalDestruct 2 -executor: totalConstruct 2 totalDestruct 2 +event: totalConstruct 8 totalDestruct 8 +thread: totalConstruct 2 totalDestruct 2 +executor: totalConstruct 2 totalDestruct 2 +linkedListNode: totalConstruct 15 totalDestruct 15 +linkedList: totalConstruct 6 totalDestruct 6 diff --git a/test/testThreadAux b/test/testThreadAux index 901c952..4b74ead 100644 --- a/test/testThreadAux +++ b/test/testThreadAux @@ -1 +1 @@ -time per call 41.194820 microseconds +time per call 37.293004 microseconds diff --git a/test/testThreadGold b/test/testThreadGold index 3e1887a..8766374 100644 --- a/test/testThreadGold +++ b/test/testThreadGold @@ -1,8 +1,8 @@ threads basic middle -linkedListNode: totalConstruct 17 totalDestruct 10 -linkedList: totalConstruct 6 totalDestruct 4 -event: totalConstruct 8 totalDestruct 8 -thread: totalConstruct 2 totalDestruct 2 -executor: totalConstruct 2 totalDestruct 2 +event: totalConstruct 8 totalDestruct 8 +thread: totalConstruct 2 totalDestruct 2 +executor: totalConstruct 2 totalDestruct 2 +linkedListNode: totalConstruct 15 totalDestruct 15 +linkedList: totalConstruct 6 totalDestruct 6 diff --git a/test/testTimeStampAux b/test/testTimeStampAux index d599870..9ad1063 100644 --- a/test/testTimeStampAux +++ b/test/testTimeStampAux @@ -1,5 +1,5 @@ -current 1293395469 853440425 milliSec 1293395469853 -2010.12.26 15:31:09 853440425 nanoSeconds isDst false +current 1294842528 236065826 milliSec 1294842528236 +2011.01.12 09:28:48 236065826 nanoSeconds isDst false fromTime_t -current 1293395469 0 milliSec 1293395469000 -2010.12.26 15:31:09 0 nanoSeconds isDst false +current 1294842528 0 milliSec 1294842528000 +2011.01.12 09:28:48 0 nanoSeconds isDst false diff --git a/test/testTimer b/test/testTimer index 4740546..9e1d103 100644 --- a/test/testTimer +++ b/test/testTimer @@ -1,6 +1,6 @@ -linkedListNode: totalConstruct 20 totalDestruct 12 -linkedList: totalConstruct 5 totalDestruct 3 -event: totalConstruct 15 totalDestruct 15 -thread: totalConstruct 3 totalDestruct 3 -timerNode: totalConstruct 6 totalDestruct 6 -timer: totalConstruct 3 totalDestruct 3 +event: totalConstruct 15 totalDestruct 15 +thread: totalConstruct 3 totalDestruct 3 +timerNode: totalConstruct 6 totalDestruct 6 +timer: totalConstruct 3 totalDestruct 3 +linkedListNode: totalConstruct 18 totalDestruct 18 +linkedList: totalConstruct 5 totalDestruct 5 diff --git a/test/testTimerAux b/test/testTimerAux index 2fb8c73..32afac2 100644 --- a/test/testTimerAux +++ b/test/testTimerAux @@ -1,6 +1,6 @@ -one requested 0.400000 diff 0.400393 seconds -two requested 0.200000 diff 0.200411 seconds -one requested 0.200000 diff 0.200244 seconds -two requested 0.400000 diff 0.400291 seconds -one requested 0.000000 diff 0.000131 seconds -two requested 0.000000 diff 0.000155 seconds +one requested 0.400000 diff 0.400196 seconds +two requested 0.200000 diff 0.200182 seconds +one requested 0.200000 diff 0.200248 seconds +two requested 0.400000 diff 0.400307 seconds +one requested 0.000000 diff 0.000033 seconds +two requested 0.000000 diff 0.000049 seconds diff --git a/test/testTimerGold b/test/testTimerGold index 4740546..9e1d103 100644 --- a/test/testTimerGold +++ b/test/testTimerGold @@ -1,6 +1,6 @@ -linkedListNode: totalConstruct 20 totalDestruct 12 -linkedList: totalConstruct 5 totalDestruct 3 -event: totalConstruct 15 totalDestruct 15 -thread: totalConstruct 3 totalDestruct 3 -timerNode: totalConstruct 6 totalDestruct 6 -timer: totalConstruct 3 totalDestruct 3 +event: totalConstruct 15 totalDestruct 15 +thread: totalConstruct 3 totalDestruct 3 +timerNode: totalConstruct 6 totalDestruct 6 +timer: totalConstruct 3 totalDestruct 3 +linkedListNode: totalConstruct 18 totalDestruct 18 +linkedList: totalConstruct 5 totalDestruct 5 diff --git a/testApp/misc/testBitSet.cpp b/testApp/misc/testBitSet.cpp index 82c3067..a5a2fb3 100644 --- a/testApp/misc/testBitSet.cpp +++ b/testApp/misc/testBitSet.cpp @@ -141,9 +141,15 @@ void testOperators() { int main(int argc,char *argv[]) { + char *fileName = 0; + if(argc>1) fileName = argv[1]; + FILE * fd = stdout; + if(fileName!=0 && fileName[0]!=0) { + fd = fopen(fileName,"w+"); + } testGetSetClearFlip(); testOperators(); - //getShowConstructDestruct()->constuctDestructTotals(stdout); + getShowConstructDestruct()->showDeleteStaticExit(fd); return(0); } diff --git a/testApp/misc/testLinkedList.cpp b/testApp/misc/testLinkedList.cpp index 0ab3ffc..1e39614 100644 --- a/testApp/misc/testLinkedList.cpp +++ b/testApp/misc/testLinkedList.cpp @@ -349,6 +349,7 @@ static void testTimeLocked(FILE *auxFd) { assert(basicList->isEmpty()); delete basicList; for(int i=0; i stdList; @@ -421,6 +422,7 @@ static void testStdListTimeLocked(FILE *auxFd) { diff = diff/(numNodes*2); // convert to per addTail/removeHead fprintf(auxFd,"time per addTail/removeHead %f microseconds\n",diff); for(int i=0; i constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return (0); } diff --git a/testApp/misc/testMessageQueue.cpp b/testApp/misc/testMessageQueue.cpp index 04c29cb..5e0e3bd 100644 --- a/testApp/misc/testMessageQueue.cpp +++ b/testApp/misc/testMessageQueue.cpp @@ -52,7 +52,7 @@ static void testBasic(FILE * fd,FILE *auxfd ) { assert(result==false); messageNode = queue->get(); assert(messageNode!=0); - fprintf(auxfd,"message %s messageType %s\n", + fprintf(fd,"message %s messageType %s\n", messageNode->getMessage().c_str(), messageTypeName[messageNode->getMessageType()].c_str()); assert(messageNode->getMessage().compare(messages[0])==0); @@ -63,7 +63,7 @@ static void testBasic(FILE * fd,FILE *auxfd ) { queue->release(); messageNode = queue->get(); assert(messageNode!=0); - fprintf(auxfd,"message %s messageType %s\n", + fprintf(fd,"message %s messageType %s\n", messageNode->getMessage().c_str(), messageTypeName[messageNode->getMessageType()].c_str()); assert(messageNode->getMessage().compare(messages[3])==0); @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) { auxfd = fopen(auxFileName,"w+"); } testBasic(fd,auxfd); - getShowConstructDestruct()->constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return (0); } diff --git a/testApp/misc/testQueue.cpp b/testApp/misc/testQueue.cpp index da2402b..c519877 100644 --- a/testApp/misc/testQueue.cpp +++ b/testApp/misc/testQueue.cpp @@ -155,7 +155,7 @@ int main(int argc, char *argv[]) { auxfd = fopen(auxFileName,"w+"); } testBasic(fd,auxfd); - getShowConstructDestruct()->constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return (0); } diff --git a/testApp/misc/testThread.cpp b/testApp/misc/testThread.cpp index 35e5b15..5c37290 100644 --- a/testApp/misc/testThread.cpp +++ b/testApp/misc/testThread.cpp @@ -115,6 +115,6 @@ int main(int argc, char *argv[]) { } testBasic(fd); testThreadContext(fd,auxFd); - getShowConstructDestruct()->constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return (0); } diff --git a/testApp/misc/testTimer.cpp b/testApp/misc/testTimer.cpp index 062e15c..8e69e02 100644 --- a/testApp/misc/testTimer.cpp +++ b/testApp/misc/testTimer.cpp @@ -112,6 +112,6 @@ int main(int argc, char *argv[]) { oneDelay = .0; twoDelay = .0; testBasic(fd,auxfd); - getShowConstructDestruct()->constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return (0); } diff --git a/testApp/property/testProperty.cpp b/testApp/property/testProperty.cpp index 3fd81f9..b34032c 100644 --- a/testApp/property/testProperty.cpp +++ b/testApp/property/testProperty.cpp @@ -243,7 +243,7 @@ int main(int argc,char *argv[]) testDisplay(fd,auxfd); testEnumerated(fd,auxfd); deleteRecords(fd,auxfd); - getShowConstructDestruct()->constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return(0); } diff --git a/testApp/pv/testIntrospect.cpp b/testApp/pv/testIntrospect.cpp index 494e3d2..f43d884 100644 --- a/testApp/pv/testIntrospect.cpp +++ b/testApp/pv/testIntrospect.cpp @@ -110,7 +110,7 @@ static void testSimpleStructure(FILE * fd) { static StructureConstPtr createPowerSupply() { String properties("alarm"); - FieldConstPtr powerSupply[3]; + FieldConstPtrArray powerSupply = new FieldConstPtr[3]; powerSupply[0] = standardField->scalar( String("voltage"),pvDouble,properties); powerSupply[1] = standardField->scalar( @@ -129,9 +129,7 @@ static void testStructureArray(FILE * fd) { builder.clear(); top->toString(&builder); fprintf(fd,"%s\n",builder.c_str()); - // create tempory PVField so that memory can be released - PVField *pvField = pvDataCreate->createPVField(0,top); - delete pvField; + top->decReferenceCount(); } int main(int argc,char *argv[]) @@ -149,7 +147,7 @@ int main(int argc,char *argv[]) testScalarArray(fd); testSimpleStructure(fd); testStructureArray(fd); - getShowConstructDestruct()->constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return(0); } diff --git a/testApp/pv/testPVAuxInfo.cpp b/testApp/pv/testPVAuxInfo.cpp index 0fbb678..2456800 100644 --- a/testApp/pv/testPVAuxInfo.cpp +++ b/testApp/pv/testPVAuxInfo.cpp @@ -92,7 +92,7 @@ int main(int argc,char *argv[]) standardPVField = getStandardPVField(); convert = getConvert(); testPVAuxInfo(fd); - getShowConstructDestruct()->constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return(0); } diff --git a/testApp/pv/testPVData.cpp b/testApp/pv/testPVData.cpp index 5349b3b..744cae8 100644 --- a/testApp/pv/testPVData.cpp +++ b/testApp/pv/testPVData.cpp @@ -282,7 +282,7 @@ int main(int argc,char *argv[]) testAppend(fd); testPVScalar(fd); testScalarArray(fd); - getShowConstructDestruct()->constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return(0); } diff --git a/testApp/pv/testPVStructureArray.cpp b/testApp/pv/testPVStructureArray.cpp index 5f64c77..e60c864 100644 --- a/testApp/pv/testPVStructureArray.cpp +++ b/testApp/pv/testPVStructureArray.cpp @@ -31,7 +31,7 @@ static String buffer(""); StructureConstPtr getPowerSupplyStructure() { String properties("alarm"); - FieldConstPtr powerSupply[3]; + FieldConstPtrArray powerSupply = new FieldConstPtr[3]; powerSupply[0] = standardField->scalar( String("voltage"),pvDouble,properties); powerSupply[1] = standardField->scalar( @@ -49,16 +49,22 @@ void testPowerSupplyArray(FILE * fd) { PVStructureArray * powerSupplyArray = powerSupplyArrayStruct->getStructureArrayField(String("value")); assert(powerSupplyArray!=0); - PVStructure *structureArray[3]; + PVStructurePtrArray structureArray = new PVStructurePtr[3]; StructureConstPtr structure = powerSupplyArray->getStructureArray()->getStructure(); + structure->incReferenceCount(); structureArray[0] = pvDataCreate->createPVStructure(0,structure); + structure->incReferenceCount(); structureArray[1] = pvDataCreate->createPVStructure(0,structure); + structure->incReferenceCount(); structureArray[2] = pvDataCreate->createPVStructure(0,structure); powerSupplyArray->put(0,3,structureArray,0); buffer.clear(); powerSupplyArrayStruct->toString(&buffer); fprintf(fd,"%s\n",buffer.c_str()); + buffer.clear(); + powerSupplyArrayStruct->getField()->dumpReferenceCount(&buffer,0); + fprintf(fd," reference counts %s\n",buffer.c_str()); delete powerSupplyArrayStruct; } @@ -75,7 +81,7 @@ int main(int argc,char *argv[]) standardField = getStandardField(); standardPVField = getStandardPVField(); testPowerSupplyArray(fd); - getShowConstructDestruct()->constuctDestructTotals(fd); + getShowConstructDestruct()->showDeleteStaticExit(fd); return(0); }