mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Cocoa Memory Management Fixups
A number of memory management errors fixed, no doubt there are more lurking in there. * CocoaInitializer now sets up an application wide NSAutoreleasePool * Kickr now init/releases an NSAutoreleasePool for its thread * Local autorelease pools in constructors etc have been removed * Searchbox and Button no longer release in the constructor The icon corruption seems to be improved (I think it is a memory management issue) but has not been totally removed.
This commit is contained in:
@@ -223,8 +223,14 @@ Kickr::find()
|
||||
int
|
||||
Kickr::connectKickr()
|
||||
{
|
||||
// get a pool for this thread
|
||||
pool = WFApi::getInstance()->getPool();
|
||||
|
||||
// do we even have BTLE hardware?
|
||||
if (WFApi::getInstance()->isBTLEEnabled() == false) return (-1);
|
||||
if (WFApi::getInstance()->isBTLEEnabled() == false) {
|
||||
WFApi::getInstance()->freePool(pool);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// discover first...
|
||||
if (scanned == false) find();
|
||||
@@ -239,7 +245,10 @@ Kickr::connectKickr()
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == false) return -1;
|
||||
if (found == false) {
|
||||
WFApi::getInstance()->freePool(pool);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
w->connectDevice(i);
|
||||
return 0;
|
||||
@@ -251,6 +260,10 @@ Kickr::disconnectKickr()
|
||||
// disconnect
|
||||
WFApi::getInstance()->disconnectDevice();
|
||||
connected = false;
|
||||
|
||||
// clear that pool now we're done
|
||||
WFApi::getInstance()->freePool(pool);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,8 @@ private:
|
||||
|
||||
QString deviceUUID;
|
||||
RealtimeData rt;
|
||||
|
||||
void *pool;
|
||||
};
|
||||
|
||||
#endif // _GC_Kickr_h
|
||||
|
||||
@@ -135,6 +135,11 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
zones_(new Zones), hrzones_(new HrZones),
|
||||
ride(NULL), workout(NULL)
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
// get an autorelease pool setup
|
||||
static CocoaInitializer cocoaInitializer;
|
||||
#endif
|
||||
|
||||
#ifdef GC_HAVE_WFAPI
|
||||
WFApi *w = WFApi::getInstance(); // ensure created on main thread
|
||||
w->apiVersion();//shutup compiler
|
||||
@@ -204,7 +209,6 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
|
||||
|
||||
#ifdef Q_OS_MAC // MAC NATIVE TOOLBAR
|
||||
static CocoaInitializer cocoaInitializer; // we only need one
|
||||
setUnifiedTitleAndToolBarOnMac(true);
|
||||
head = addToolBar(cyclist);
|
||||
head->setContentsMargins(0,0,0,0);
|
||||
@@ -220,13 +224,15 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
QHBoxLayout *lb = new QHBoxLayout(macAnalButtons);
|
||||
lb->setContentsMargins(0,0,0,0);
|
||||
lb->setSpacing(0);
|
||||
QtMacButton *import = new QtMacButton(this, QtMacButton::TexturedRounded);
|
||||
import->setImage(QPixmap(":images/mac/download.png"));
|
||||
import = new QtMacButton(this, QtMacButton::TexturedRounded);
|
||||
QPixmap importImg(":images/mac/download.png");
|
||||
import->setImage(importImg);
|
||||
import->setToolTip("Download");
|
||||
lb->addWidget(import);
|
||||
lb->addWidget(new Spacer(this));
|
||||
QtMacButton *compose = new QtMacButton(this, QtMacButton::TexturedRounded);
|
||||
compose->setImage(QPixmap(":images/mac/compose.png"));
|
||||
compose = new QtMacButton(this, QtMacButton::TexturedRounded);
|
||||
QPixmap composeImg(":images/mac/compose.png");
|
||||
compose->setImage(composeImg);
|
||||
compose->setToolTip("Create");
|
||||
lb->addWidget(compose);
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ class Lucene;
|
||||
class NamedSearches;
|
||||
class ChartSettings;
|
||||
class QtMacSegmentedButton;
|
||||
class QtMacButton;
|
||||
class GcScopeBar;
|
||||
class RideFileCache;
|
||||
class Library;
|
||||
@@ -444,6 +445,7 @@ class MainWindow : public QMainWindow
|
||||
// Mac Native Support
|
||||
QWidget *toolBarWidgets;
|
||||
QWidget *macAnalButtons;
|
||||
QtMacButton *import, *compose;
|
||||
QtMacSegmentedButton *styleSelector;
|
||||
QToolBar *head;
|
||||
GcScopeBar *scopebar;
|
||||
|
||||
@@ -27,7 +27,6 @@ static NSImage *fromQPixmap(const QPixmap &pixmap)
|
||||
NSImage *image = [[NSImage alloc] init];
|
||||
[image addRepresentation:bitmapRep];
|
||||
[image setTemplate:true];
|
||||
[bitmapRep release];
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -205,10 +204,7 @@ QtMacButton::QtMacButton(QWidget *parent, BezelStyle bezelStyle) : QWidget(paren
|
||||
[button setTarget:target];
|
||||
|
||||
[button setAction:@selector(clicked)];
|
||||
|
||||
setupLayout(button, this);
|
||||
|
||||
[button release];
|
||||
}
|
||||
|
||||
void QtMacButton::setWidth(int x)
|
||||
@@ -240,7 +236,7 @@ void QtMacButton::setImage(const QPixmap &image)
|
||||
Q_ASSERT(qtw);
|
||||
if (qtw) {
|
||||
[qtw->nsButton setImage:fromQPixmap(image)];
|
||||
//[qtw->nsButton setAlternateImage:fromQPixmap(image)];
|
||||
[qtw->nsButton setAlternateImage:fromQPixmap(image)];
|
||||
[qtw->nsButton setButtonType:NSMomentaryPushButton];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ static NSImage *fromQPixmap(const QPixmap &pixmap)
|
||||
NSImage *image = [[NSImage alloc] init];
|
||||
[image addRepresentation:bitmapRep];
|
||||
[image setTemplate:true];
|
||||
[bitmapRep release];
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -191,8 +190,6 @@ QtMacPopUpButton::QtMacPopUpButton(QWidget *parent, BezelStyle bezelStyle) : QWi
|
||||
[button setAction:@selector(clicked)];
|
||||
|
||||
setupLayout(button, this);
|
||||
|
||||
[button release];
|
||||
}
|
||||
|
||||
void QtMacPopUpButton::setToolTip(const QString &text)
|
||||
|
||||
@@ -79,10 +79,6 @@ SearchWidget::SearchWidget(QtMacSearchBox *parent)
|
||||
//QMenu *qtMenu = createMenu(this);
|
||||
//NSMenu *nsMenu = qtMenu->macMenu(0);
|
||||
//[[search cell] setSearchMenuTemplate:nsMenu];
|
||||
|
||||
// Release our reference, since our super class takes ownership and we
|
||||
// don't need it anymore.
|
||||
[search release];
|
||||
}
|
||||
|
||||
SearchWidget::~SearchWidget()
|
||||
|
||||
@@ -21,26 +21,8 @@
|
||||
|
||||
#include <QMacCocoaViewContainer>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Cocoa / OBJC helpers etc
|
||||
//
|
||||
// this is a utility -- since this source file
|
||||
// is included in C++ and Objective-C code the
|
||||
// declaration of native components is referenced
|
||||
// directly or just as a void *
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class CocoaInitializer
|
||||
{
|
||||
public:
|
||||
CocoaInitializer();
|
||||
~CocoaInitializer();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private* d;
|
||||
};
|
||||
|
||||
// macros for compile time, depending if included in an obj-c
|
||||
// or a c++ source file. Changes declaration of class types.
|
||||
#ifdef __OBJC__
|
||||
# define ADD_COCOA_NATIVE_REF(CocoaClass) \
|
||||
@class CocoaClass; \
|
||||
@@ -49,12 +31,18 @@ class CocoaInitializer
|
||||
# define ADD_COCOA_NATIVE_REF(CocoaClass) typedef void *Native##CocoaClass##Ref
|
||||
#endif /* __OBJC__ */
|
||||
|
||||
// The above is merely to do the following, but
|
||||
// we may add more native widgets in the future
|
||||
ADD_COCOA_NATIVE_REF (NSSegmentedControl);
|
||||
ADD_COCOA_NATIVE_REF (NSAutoreleasePool);
|
||||
class CocoaInitializer
|
||||
{
|
||||
public:
|
||||
CocoaInitializer();
|
||||
~CocoaInitializer();
|
||||
|
||||
// The native Cocoa segmented button is held within
|
||||
// a QMacCocoaView container.
|
||||
private:
|
||||
NativeNSAutoreleasePoolRef pool;
|
||||
};
|
||||
|
||||
ADD_COCOA_NATIVE_REF (NSSegmentedControl);
|
||||
class QtMacSegmentedButton : public QMacCocoaViewContainer
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
@@ -25,23 +25,15 @@
|
||||
#import <AppKit/NSSegmentedControl.h>
|
||||
#import <AppKit/NSBezierPath.h>
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* Utility functions
|
||||
*----------------------------------------------------------------------*/
|
||||
class CocoaInitializer::Private
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
CocoaInitializer::CocoaInitializer()
|
||||
{
|
||||
d = new CocoaInitializer::Private();
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
NSApplicationLoad();
|
||||
}
|
||||
|
||||
CocoaInitializer::~CocoaInitializer()
|
||||
{
|
||||
delete d;
|
||||
[pool release];
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +48,6 @@ static NSImage *fromQPixmap(const QPixmap &pixmap)
|
||||
NSImage *image = [[NSImage alloc] init];
|
||||
[image addRepresentation:bitmapRep];
|
||||
[image setTemplate:true];
|
||||
[bitmapRep release];
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,15 @@ public:
|
||||
void setSlope(double slope);
|
||||
void setLoad(int watts);
|
||||
|
||||
// NOTE: There is an application wide NSAutoreleasePool maintained
|
||||
// in cocoa initialiser, but it is only to support activity on
|
||||
// the main thread.
|
||||
// The application code (e.g. Kickr.cpp) needs to get and free a
|
||||
// pool for each thread, this is why we have a getPool/freePool
|
||||
// method in WFApi, but never allocate a pool ourselves.
|
||||
void *getPool();
|
||||
void freePool(void*);
|
||||
|
||||
signals:
|
||||
void currentStateChanged(int); // hardware conncector state changed
|
||||
int discoveredDevices(int,bool);
|
||||
|
||||
23
src/WFApi.mm
23
src/WFApi.mm
@@ -53,6 +53,7 @@ static QString toQString(const NSString *nsstr)
|
||||
// Objective C -- Private interface / Bridge to WF API classes
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
@interface WFBridge : NSObject <WFHardwareConnectorDelegate, WFSensorConnectionDelegate> {
|
||||
@public
|
||||
QPointer<WFApi> qtw; // the QT QObject public class
|
||||
@@ -82,9 +83,7 @@ static QString toQString(const NSString *nsstr)
|
||||
// By default BTLE is disabled
|
||||
-(BOOL)isBTLEEnabled { return [[WFHardwareConnector sharedConnector] isBTLEEnabled]; }
|
||||
-(BOOL)enableBTLE:(BOOL)bEnable inBondingMode:(BOOL)bBondingMode {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
bool result = [[WFHardwareConnector sharedConnector] enableBTLE:bEnable inBondingMode:bBondingMode];
|
||||
[pool drain];
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -105,10 +104,8 @@ static QString toQString(const NSString *nsstr)
|
||||
// scan
|
||||
-(BOOL)discoverDevicesOfType:(WFSensorType_t)eSensorType onNetwork:(WFNetworkType_t)eNetworkType searchTimeout:(NSTimeInterval)timeout
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[discoveredSensors removeAllObjects];
|
||||
[[WFHardwareConnector sharedConnector] discoverDevicesOfType:eSensorType onNetwork:eNetworkType searchTimeout:timeout]; //XXX ignoringreturn
|
||||
[pool drain];
|
||||
return true;
|
||||
}
|
||||
-(int)deviceCount { return [discoveredSensors count]; }
|
||||
@@ -120,7 +117,6 @@ static QString toQString(const NSString *nsstr)
|
||||
|
||||
-(BOOL)connectDevice: (int)n
|
||||
{
|
||||
//NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
|
||||
// just in case there is a discovery in action, lets cancel it...
|
||||
[[WFHardwareConnector sharedConnector] cancelDiscoveryOnNetwork:WF_NETWORKTYPE_BTLE];
|
||||
|
||||
@@ -138,7 +134,6 @@ static QString toQString(const NSString *nsstr)
|
||||
// set delegate to receive connection status changes.
|
||||
self.sensorConnection.delegate = self;
|
||||
|
||||
//[pool drain];
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -218,6 +213,8 @@ static QString toQString(const NSString *nsstr)
|
||||
qtw->hasFirmwareUpdateAvalableForConnection(); //XXX do what?
|
||||
}
|
||||
|
||||
-(NSAutoreleasePool*) getPool { return [[NSAutoreleasePool alloc] init]; }
|
||||
-(void) freePool:(NSAutoreleasePool*)pool { [pool release]; }
|
||||
@end
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -229,10 +226,8 @@ WFApi *_gc_wfapi = NULL;
|
||||
// Construct the bridge to the WF API
|
||||
WFApi::WFApi()
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
wf = [[WFBridge alloc] init];
|
||||
wf->qtw = this;
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
// Destroy the bridge to the WF API
|
||||
@@ -372,3 +367,15 @@ WFApi::getRealtimeData(RealtimeData *rt)
|
||||
rt->setCadence((int)[sd instantCadence]);
|
||||
rt->setWheelRpm((int)[sd instantWheelRPM]);
|
||||
}
|
||||
|
||||
void *
|
||||
WFApi::getPool()
|
||||
{
|
||||
return (void*)[wf getPool];
|
||||
}
|
||||
|
||||
void
|
||||
WFApi::freePool(void *pool)
|
||||
{
|
||||
[wf freePool:(NSAutoreleasePool*)pool];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user