add lock free queue

This commit is contained in:
canpadawan
2016-06-15 18:18:56 +02:00
parent f36d432b50
commit 80719b253b
14 changed files with 367 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
#ifndef CANCONCONST_H
#define CANCONCONST_H
#endif // CANCONCONST_H
+6
View File
@@ -0,0 +1,6 @@
#include "canconfactory.h"
CanConFactory::CanConFactory()
{
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef CANCONFACTORY_H
#define CANCONFACTORY_H
class CanConFactory
{
public:
CanConFactory();
};
#endif // CANCONFACTORY_H
+6
View File
@@ -0,0 +1,6 @@
#include "canconnection.h"
CanConnection::CanConnection()
{
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef CANCONNECTION_H
#define CANCONNECTION_H
class CanConnection
{
public:
CanConnection();
};
#endif // CANCONNECTION_H
+6
View File
@@ -0,0 +1,6 @@
#include "cvretserial.h"
CVRetSerial::CVRetSerial()
{
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef CVRETSERIAL_H
#define CVRETSERIAL_H
class CVRetSerial
{
public:
CVRetSerial();
};
#endif // CVRETSERIAL_H
+157
View File
@@ -0,0 +1,157 @@
#include <QObject>
#include <QDebug>
#include <QCanBusFrame>
#include "canframemodel.h"
#include "canconnection_old.h"
#include "socketcanconnection.h"
/***********************************/
/**** nested class ****/
/***********************************/
BUSConfig::BUSConfig():isConfigured(false){}
void BUSConfig::reset() {
isConfigured = false;
}
bool BUSConfig::operator==(CANBus& bus) {
return isConfigured && speed == bus.speed &&
listenOnly == bus.listenOnly && active == bus.active;
}
void BUSConfig::operator=(CANBus& bus) {
isConfigured = true;
speed = bus.speed;
listenOnly = bus.listenOnly;
active = bus.active;
}
/***********************************/
/**** class definition ****/
/***********************************/
SocketCanConnection::SocketCanConnection(CANFrameModel *model, int base) : CANConnection(model, base), mDev_p(NULL)
{
qDebug() << "SocketCanConnection()";
qRegisterMetaType<CANFrame>("CANFrame");
}
SocketCanConnection::~SocketCanConnection()
{
qDebug() << "~SocketCanConnection()";
/* stop device */
}
void SocketCanConnection::updateBusSettings(CANBus bus)
{
qDebug()<<"updateBusSettings";
if(mConf == bus) return;
/* disconnect device if we have one connected */
if(mDev_p) disconnect();
/* if bus is not active we are done */
if(!bus.active) return;
/* create device */
mDev_p = QCanBus::instance()->createDevice("socketcan", portName);
if (!mDev_p) {
qDebug() << "can't create device";
return;
}
/* connect slots */
connect(mDev_p, &QCanBusDevice::errorOccurred, this, &SocketCanConnection::errorReceived);
connect(mDev_p, &QCanBusDevice::framesReceived, this, &SocketCanConnection::framesReceived);
connect(mDev_p, &QCanBusDevice::framesWritten, this, &SocketCanConnection::framesWritten);
/* set configuration */
/*if (p.useConfigurationEnabled) {
foreach (const SettingsDialog::ConfigurationItem &item, p.configurations)
mDev->setConfigurationParameter(item.first, item.second);
}*/
/* connect device */
if (!mDev_p->connectDevice()) {
disconnect();
qDebug() << "can't connect device";
}
}
/***********************************/
/**** private methods ****/
/***********************************/
/* connect device */
void SocketCanConnection::disconnect() {
if(mDev_p) {
mDev_p->disconnectDevice();
delete mDev_p;
mDev_p = Q_NULLPTR;
}
}
void SocketCanConnection::errorReceived(QCanBusDevice::CanBusError error) const
{
switch (error) {
case QCanBusDevice::ReadError:
case QCanBusDevice::WriteError:
case QCanBusDevice::ConnectionError:
case QCanBusDevice::ConfigurationError:
case QCanBusDevice::UnknownError:
qWarning() << mDev_p->errorString();
default:
break;
}
}
void SocketCanConnection::framesWritten(qint64 count)
{
qDebug() << "Number of frames written:" << count;
}
void SocketCanConnection::framesReceived()
{
/* sanity checks */
if(!mDev_p) return;
/* read frame */
while(true)
{
const QCanBusFrame recFrame = mDev_p->readFrame();
/* exit case */
if(!recFrame.isValid()) return;
if(!recFrame.payload().isEmpty() &&
recFrame.payload().length()<=8)
{
CANFrame frame;
frame.len = recFrame.payload().length();
frame.bus = 0;
memcpy(frame.data, recFrame.payload().data(), frame.len);
frame.extended = false;
frame.ID = recFrame.frameId();
frame.isReceived = true;
frame.timestamp = recFrame.timeStamp().microSeconds();
/* send frame */
QMetaObject::invokeMethod(model, "addFrame",
Qt::QueuedConnection,
Q_ARG(CANFrame, frame),
Q_ARG(bool, false));
}
else {
qDebug() << "invalid frame";
}
}
}
+44
View File
@@ -0,0 +1,44 @@
#ifndef SOCKETCANCONNECTION_H
#define SOCKETCANCONNECTION_H
#include <QObject>
#include <QCanBus>
#include "canframemodel.h"
#include "canconnection_old.h"
class BUSConfig {
public:
BUSConfig();
void reset();
bool operator ==(CANBus&);
void operator =(CANBus&);
bool isConfigured;
int speed;
bool listenOnly;
bool active;
};
class SocketCanConnection : public CANConnection
{
Q_OBJECT
public:
SocketCanConnection(CANFrameModel *, int);
virtual ~SocketCanConnection() override;
public slots:
virtual void updateBusSettings(CANBus) override;
private:
void errorReceived(QCanBusDevice::CanBusError error) const;
void framesWritten(qint64 count);
void framesReceived();
void disconnect();
QCanBusDevice* mDev_p;
BUSConfig mConf;
};
#endif // SOCKETCANCONNECTION_H
+12
View File
@@ -0,0 +1,12 @@
QT += core
QT -= gui
CONFIG += c++11
TARGET = test
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
+8
View File
@@ -0,0 +1,8 @@
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
return a.exec();
}
+91
View File
@@ -0,0 +1,91 @@
#ifndef LFQUEUE_H
#define LFQUEUE_H
#include <QObject>
#include <QDebug>
/* macros */
#define IS_EMPTY() ( mWIdx.load() == mRIdx.load() )
#define IS_FULL() ( (mWIdx.load()+1)%mSize == mRIdx.load() )
template<class T>
class LFQueue
{
public:
LFQueue() : mSize(0), mArray(NULL){}
~LFQueue() {setSize(0);}
bool setSize(int size) {
if(size<0)
return false;
if(mArray) {
delete[] mArray;
mArray = NULL;
}
if(size>0) {
mArray = new T[size];
if(mArray)
mSize = size;
return ( mArray!=NULL );
}
return true;
}
void flush() {
mRIdx.store(0);
mWIdx.store(0);
}
T* get() {
if(IS_FULL())
return NULL;
return &(mArray[mWIdx.loadAcquire()]); /* prevent memory reordering (belt and braces) */
}
void queue() {
#ifdef QT_DEBUG
if(IS_FULL())
qCritical() << "BUG: queueing in full queue";
#endif
int wIdx = mWIdx.load();
mWIdx.storeRelease((wIdx+1)%mSize);
}
T* peek() {
if(IS_EMPTY())
return NULL;
return &(mArray[mRIdx.loadAcquire()]); /* prevent memory reordering (belt and braces) */
}
void dequeue() {
#ifdef QT_DEBUG
if(IS_EMPTY())
qCritical() << "BUG: dequeueing an empty queue";
#endif
int rIdx = mRIdx.load();
mRIdx.storeRelease((rIdx+1)%mSize);
}
private:
int mSize;
T* mArray;
QAtomicInt mRIdx;
QAtomicInt mWIdx;
};
#endif // LFQUEUE_H