add lock free queue
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef CANCONCONST_H
|
||||||
|
#define CANCONCONST_H
|
||||||
|
|
||||||
|
#endif // CANCONCONST_H
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "canconfactory.h"
|
||||||
|
|
||||||
|
CanConFactory::CanConFactory()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef CANCONFACTORY_H
|
||||||
|
#define CANCONFACTORY_H
|
||||||
|
|
||||||
|
|
||||||
|
class CanConFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CanConFactory();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CANCONFACTORY_H
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "canconnection.h"
|
||||||
|
|
||||||
|
CanConnection::CanConnection()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef CANCONNECTION_H
|
||||||
|
#define CANCONNECTION_H
|
||||||
|
|
||||||
|
|
||||||
|
class CanConnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CanConnection();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CANCONNECTION_H
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "cvretserial.h"
|
||||||
|
|
||||||
|
CVRetSerial::CVRetSerial()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef CVRETSERIAL_H
|
||||||
|
#define CVRETSERIAL_H
|
||||||
|
|
||||||
|
|
||||||
|
class CVRetSerial
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CVRetSerial();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CVRETSERIAL_H
|
||||||
@@ -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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
QT += core
|
||||||
|
QT -= gui
|
||||||
|
|
||||||
|
CONFIG += c++11
|
||||||
|
|
||||||
|
TARGET = test
|
||||||
|
CONFIG += console
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
SOURCES += main.cpp
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user