Generalizing a reference counting class for use with non-specific protected classes - reference-counting

Trying to retro-fit a non-COM class with reference count based protection that prevents its deconstruction when any of its members methods are currently in process.
Wrote a small class designed to call AddRef on construction, and Release on deconstruction; declare an instance upon entry into the protected classes member functions - works OK, but it's bound to protected class which means I can only use it with that class.
I would like to generalize it so that it can be used with any class. I was thinking maybe templates would help, but I don't know enough about them to write classes that use them. Here's the class as it exists now, working, but limited to being used within ClsEditWndData instances
#ifndef _ClsProtectMe_h_
# define _ClsProtectMe_h_
typedef void (ClsEditWndData::*pfnREFCOUNTER)();
class ClsProtectMe
{
public:
ClsProtectMe( // constructor
pfnREFCOUNTER pfnAddRef, // pointer to callers' AddRef
pfnREFCOUNTER pfnRelease, // pointer to callers' Release
ClsEditWndData* pThis ) : // pointer to caller
m_pfnAddRef( pfnAddRef ), // init stored AddRef address
m_pfnRelease( pfnRelease ), // init stored Release address
m_pThis( pThis ) // init stored instance address
{ // ===========================
if( m_pThis != NULL ) // must have non-null instance
if( m_pfnRelease != NULL ) // must have non-null release
if( m_pfnAddRef != NULL ) // must have non-null addref
(m_pThis->*m_pfnAddRef)(); // call the addref function
} // ===========================
virtual ~ClsProtectMe(void) // destructor
{ // ===========================
if( m_pThis != NULL ) // must have non-null instance
if( m_pfnRelease != NULL ) // must have non-null release
if( m_pfnAddRef != NULL ) // must have non-null addref
(m_pThis->*m_pfnRelease)(); // call the release function
} // ===========================
private:
pfnREFCOUNTER m_pfnAddRef; // stored pointer to AddRef function
pfnREFCOUNTER m_pfnRelease; // stored pointer to Release function
ClsEditWndData* m_pThis; // stored pointer to instance
};
#endif

Solution was a lot easier than I expected. A little research into template classes gave me the answer I was looking for. I was able to 'templateize' the above class as follows:
template <class T> class ClsProtect
{
public:
ClsProtect( void (T::*add)(), void (T::*release)(), T* pThis )
: m_pfnAdd( add ), m_pfnRelease( release ), m_pThis( pThis )
{
if( m_pThis != NULL )
if( m_pfnAdd != NULL )
if( m_pfnRelease != NULL )
(m_pThis->*m_pfnAdd)();
};
virtual ~ClsProtect(){
if( m_pThis != NULL )
if( m_pfnAdd != NULL )
if( m_pfnRelease != NULL )
(m_pThis->*m_pfnRelease)();
};
private:
void (T::* m_pfnAdd)();
void (T::* m_pfnRelease)();
T* m_pThis;
};
usage:
void ClsEditWndData::OnKeyDown( WPARAM wParam, LPARAM )
{
ClsProtect<ClsEditWndData> objProtect(
&ClsEditWndData::AddRef,
&ClsEditWndData::Release,
this );
...<whatever, don't care...>...
}

Related

How to iterate items in Multi-dimensional Systemverilog uvm_queue

I’m trying to create an object which is constructed from array of uvm_queue. The idea is that each item in the array is for itself a uvm_queue ( i.e. a list of items). The Queue type is a class.
The problem is I can’t manage to iterate the items of a single ‘memory ID’ list.
When I compile I get the following Error:
if (ml_mem_array[mem_id][ii].m_addr == a_addr)
xmelab: *E,CUVNAA (./utils.sv,47|45): An index has been applied to an inappropriate type.
The code looks like this:
// ====================
class mem_entry extends uvm_object;
int m_addr;
int m_data;
endclass
// ====================
class memory extends uvm_object;
uvm_queue#(mem_entry) ml_mem_array[2];
function mem_entry get_mem_entry(int a_addr, int mem_id);
int v_size;
int ii;
v_size = ml_mem_array[mem_id].size();
if ((mem_id >= 2) || (v_size == 0))
return null;
for (ii=0 ; ii<=(v_size-1) ; ii=ii+1)
begin
if (ml_mem_array[mem_id][ii].m_addr == a_addr)
return ml_mem_array[mem_id][ii];
end
return null;
endfunction
endclass
You need to use the get() method of uvm_queue to access the internal queue elements
for (int ii=0 ; ii<=(v_size-1) ; ii=ii+1)
begin
mem_entry entry = ml_mem_array[mem_id].get(ii);
if (entry.m_addr == a_addr)
return entry;
end

Overloading == and !== when object is a pointer

I am new to writing operators (in this case == and !=). I have done a bit of research and so far came up with:
bool operator==(const SPECIAL_EVENT_S &rsEvent)
{
bool bSame = false;
if (rsEvent.datEvent == m_datSpecialEvent &&
rsEvent.strEvent == m_strNotes &&
rsEvent.strLocation == m_strLocation &&
rsEvent.datEventStartTime == m_datEventStartTime &&
rsEvent.datEventFinishTime == m_datEventFinishTime &&
gsl::narrow<bool>(rsEvent.bEventAllDay) == m_bEventAllDay &&
gsl::narrow<bool>(rsEvent.bSetReminder) == m_bSetReminder &&
rsEvent.iReminderUnitType == m_iReminderUnitType &&
rsEvent.iReminderInterval == m_iReminderInterval &&
rsEvent.iImageWidthPercent == m_wImageWidthPercent &&
rsEvent.strImagePath == m_strImagePath &&
rsEvent.strTextBeforeImage == m_strTextBeforeImage &&
rsEvent.strTextAfterImage == m_strTextAfterImage &&
rsEvent.eType == m_eVideoconfType &&
rsEvent.sBSSTI == m_sBSSTI)
{
// The fundamental information is unchanged
bSame = true;
}
// Now compare the MWB Event Type
if (bSame)
{
switch (rsEvent.eMWBEventType)
{
case EventTypeMWB::MWBBethelSpeakerServiceTalk:
return m_bSpecialEventBethelServiceTalk;
case EventTypeMWB::MWBVideoconferenceAssembly:
return m_bSpecialEventVideoconf && m_eVideoconfType == VideoConferenceEventType::Live;
case EventTypeMWB::MWBVideoconferenceConvention:
return m_bSpecialEventVideoconf && m_eVideoconfType == VideoConferenceEventType::Recorded;
case EventTypeMWB::MWBSpecialEvent:
return m_bSpecialEvent;
case EventTypeMWB::MWBMemorial:
return m_bEventMemorial;
case EventTypeMWB::MWBCircuitOverseerMeeting:
return m_bCircuitVisit || m_bCircuitVisitGroup;
case EventTypeMWB::MWBMeeting:
return !m_bNoMeeting;
default:
bSame = false;
}
}
return bSame;
}
bool operator!=(const SPECIAL_EVENT_S& rsEvent)
{
return !(rsEvent == *this);
}
What surprised me what when I then tried to use these operators:
if (pEntry != sEvent)
{
AfxMessageBox(_T("The special event information has changed"));
}
It does not like pEntry being a pointer. In the end I did this:
if (*pEntry != sEvent)
{
AfxMessageBox(_T("The special event information has changed"));
}
Why was this an issue in the first place? I ask that because if this was a standard function it would not matter if the object was a pointer or not.
What is the correct way to cater for this scenario?
For example:
object->Function(value)
object.Function(value)
Function can be used both by the object when it is / is not a pointer. So why not with an operator?
Function can be used both by the object when it is / is not a pointer.
Actually, no it can't. In a statement/expression like object->Function(value) the -> (member access) and () (function call) operators have the same precedence and left-to-right associativity. So, the -> is applied first and that automatically dereferences the pointer. So, the effect is the same as (*object).Function(value) – and Function is still being called on an object, rather than on a pointer.
So why not with an operator?
The syntax for calling an operator function is (or can be) rather different: because it is defined as an operator, you can call it using the operator token (between the two operands) rather than by using an explicit function call. But then, you have to pass objects, as that's what the operands are defined to be.
However, should you really want to, you can still call an operator override using explicit function-call syntax; and, in that case, you can use the -> on a pointer; like this (where operator== is effectively the 'name' of the function):
if (!pEntry->operator==(sEvent))
{
AfxMessageBox(_T("The special event information has changed"));
}
However, this seems like a lot of hard work and your *pEntry != sEvent is actually the 'correct' way to use the override.
PS: As bonus, if you're using a compiler that supports the C++20 (or later) Standard, you can add a "defaulted" operator== to your structures/classes, which would save you explicitly comparing each individual data member:
struct foo {
int a;
double b;
bool operator==(const foo&) const = default; // Compares "a" and "b"
};
struct bar {
foo f;
int c;
int d;
bool operator==(const bar&) const = default; // Compares "c", "d" and "f"
};

QHeaderView::mousePressEvent (need to figure out the column/index)

Generally I can get this to work no problem when I reimplement QTableView::mousePressEvent( QMouseEvent* ). However, doing it on QHeaderView is not working for me. Code is simple.
void my_header_t::mousePressEvent( QMouseEvent* event )
{
if ( !event ) {
return;
}
if ( event->button() == Qt::RightButton ) {
QPoint point( event->x(), event->y() );
QModelIndex index = indexAt( point );
printf( "%s data %s %d,%d %s (point: %d,%d )\n",
ts().c_str(), index.data().toString().toStdString().c_str(),
index.row(), index.column(), index.isValid() ? "True" : "False",
event->x(), event->y() );
handle_right_click( index.data().toString() );
} else {
QHeaderView::mousePressEvent( event );
}
x() and y() from the QMouseEvent are fine. However, it creates an invalid index, with row() of -1, and column() of -1. Obviously, I'm passing an empty string to handle_right_click() which kicks off a menu. That menu is not going to know which column called it, and the mayhem will further ensue.
I know that clicked( const QModelIndex& ) will just tell me the right index, with the text. However, I need to differentiate between buttons.
QHeaderView provides an alternative function, logicalIndexAt, for determining the index of the header item that you're interested in. Using your code from above:
void my_header_t::mousePressEvent( QMouseEvent* event )
{
if ( !event ) {
return;
}
if ( event->button() == Qt::RightButton ) {
int index = logicalIndexAt( event->pos() );
handle_right_click(model()->headerData(index, Qt::Horizontal).toString());
} else {
QHeaderView::mousePressEvent( event );
}
}
Note that the orientation of the header must be passed to the headerData method (in this case, I've just assumed that it's Qt::Horizontal, but in your case it might be something different).

QtInputContextFactory returning NULL on embedded target

On my embedded system I don't have X11, Mac, Win, S60, etc. I keep getting a NULL ( 0 ) pointer returned from the create method of the QInputContextFactory class. I verified that QT_NO_LIBRARY is not defined.
On my Desktop Qt Build this works just fine.
I also verified that my custom key and parent are being passed to the method.
What could cause this to fail? -->
if (QInputContextFactoryInterface *factory =
qobject_cast<QInputContextFactoryInterface*>(loader()->instance(key))) {
result = factory->create(key);
}
Here is the entire method:
QInputContext *QInputContextFactory::create( const QString& key, QObject *parent )
{
QInputContext *result = 0;
#if defined(Q_WS_X11) && !defined(QT_NO_XIM)
if (key == QLatin1String("xim")) {
result = new QXIMInputContext;
}
#endif
#if defined(Q_WS_WIN)
if (key == QLatin1String("win")) {
result = new QWinInputContext;
}
#endif
#if defined(Q_WS_MAC)
if (key == QLatin1String("mac")) {
result = new QMacInputContext;
}
#endif
#if defined(Q_WS_S60)
if (key == QLatin1String("coefep")) {
result = new QCoeFepInputContext;
}
#endif
#ifdef QT_NO_LIBRARY
Q_UNUSED(key);
#else
qDebug() << "Here we are";
if (QInputContextFactoryInterface *factory =
qobject_cast<QInputContextFactoryInterface*>(loader()->instance(key))) {
result = factory->create(key);
}
#endif
if (result)
result->setParent(parent);
return result;
}
Within Qt, the QInputContextFactory class is front-end on loading input context plug-ins. It will fail to load an input context plug-in if it fails to exist, or hasn't been deployed properly. Input context plug-ins are typically stored under $QT_PLUGIN_PATH/inputmethods. As such, if there is no plug-in within that directory, the create method of the QInputContextFactory will return NULL.
Of note, Qt does provide a few mechanisms for customizing the location of plug-ins. Refer to the following for more detail on this:
http://qt-project.org/doc/qt-4.8/deployment-plugins.html

Call by reference with QVector

I have in an Object an QVector of Coordinates (my type) that I want to transfer to an other Vector ( I validate and than want to use ist ).
Header
bool getVector(QVector<Coordinates> &getCoordinates );
C File
static QVector<Coordinates> current;
int getVector( QVector<Coordinates> &getCoordinates)
{
.... stuff ...
getCoordinates = current;
.... stuff ....
return 0;
}
And I use it like
....
QVector<Coordinates> currentCoordinates;
getVector(currentCoordinates);
currentCoordinates.X // CRASH
The debugger goes to this line where an Live Crash happens
inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
So my how can I fix this? As I can use this to get all the other Variables with this methode.
A likely cause of your problem is that current has not been constructed before getVector is called. Initialization of static objects in C++ is a thorny area, and a frequent source of bugs - for more information, see this question, and the static initialization order fiasco FAQ entry.
A simple solution to this problem is to provide access to current via a function, i.e. replace
static QVector<Coordinates> current;
with
static QVector<Coordinates>& getCurrent()
{
static QVector<Coordinates> current;
return current;
}
Note, however, that the function as written above is not thread-safe. If multiple threads may call getCurrent, then it should be protected with a QMutex.
For gareth and the Forum :
the header:
typedef QVector<Coordinates> VesselCoordinates;
bool (*getVessel)(Charakter forCharakter, Vessel& getVessel,VesselCoordinates &getCoordinates );
later i bind tis function pointer to an static function ( cause this part of my Program will be one day convertet to c)
cpp file lower layer:
static struct {
Charakter currentPlayerVessel;
VesselCoordinates possibility;
}data;
static bool getVessel(Charakter forCharakter, Vessel& getVessel,VesselCoordinates &getCoordinates );
// funktion to bind the funktion pointer to this static funktion so it can be called outside the File
static bool serverNamespace::getVessel(Charakter forCharakter, Vessel& getVessel,VesselCoordinates &getCoordinates )
{
bool retValue= false;
if ( forCharakter == data.currentPlayerVessel){
// TODO abfragen ob die Adresse regestriert ist!
if ((true == minSize()) and ((true == shipsInRow())or (true == shipsInLine())))
{
retValue = true;
Vessel test = (Vessel)data.possibility.size();
getVessel = test;
getCoordinates = data.possibility;
}
}
return retValue;
}
And then i can use this in the upper layer cpp file to get the information i need:
// in an Funktion :
VesselCoordinates currentCoordinates;
currentCoordinates.clear();
Vessel currentVessel;
if (true == basicFleet->getVessel(currentCharakter,currentVessel, currentCoordinates ))
// doing stuff to it
so its worik fine but your idea worked just as fine. Maybe you can see why my idea is also working.
Thank you
elektor

Resources