2020년 11월 27일 금요일

C# 빅엔디안 처리 - C# Convert big-endian to variable

버퍼에 빅엔디안으로 데이터가 있고 이것을 변수에 담아야 할때 아래 코드를 사용하면 된다.


 private uint ConvertBigEndianUInt(byte[] buffer, int offset)  
 {  
   uint ret = (uint)(buffer[offset] << 24);  
   ret |= (uint)(buffer[offset + 1] << 16);  
   ret |= (uint)(buffer[offset + 2] << 8);  
   ret |= (uint)(buffer[offset + 3]);  
   return ret;  
 }  
   
 private ushort ConvertBigEndianUShort(byte[] buffer, int offset)  
 {  
   ushort ret = (ushort)(buffer[offset] << 8);  
   ret |= (ushort)(buffer[offset + 1]);  
   return ret;  
 }  
 
 private long ConvertBigEndianLong(byte[] buffer, int offset)
 {
   long ret = (long)(buffer[offset] << 56);
   ret |= (long)(buffer[offset + 1] << 48);
   ret |= (long)(buffer[offset + 2] << 40);
   ret |= (long)(buffer[offset + 3] << 32);
   ret |= (long)(buffer[offset + 4] << 24);
   ret |= (long)(buffer[offset + 5] << 16);
   ret |= (long)(buffer[offset + 6] << 8);
   ret |= (long)(buffer[offset + 7]);
   return ret;
 }

2020년 11월 16일 월요일

QT moveToThread 방식으로 쓰레드 생성시 QThread wait 함수 사용

 QThread 상속으로 쓰레드를 생성하지않고 QObject의 moveToThread 함수로 쓰레드를 생성할때 QThread의 wait 함수를 사용하면 무한 블러킹에 걸린다.

이때 

connect(worker, SIGNAL(finished()), thread, SLOT(quit()));

와 같은 방법으로 worker 에서 finished 를 emit 하고 thread 가 받아서 quit 하게 하여도 마찬가지로 wait 에서는 무한 블러킹에 걸린다

방법은 오직 thread->exit() 과 같이 QThread의 exit 함수를 호출하는 방법 밖에 없었다.

따라서 다음과 같이 구현하면 Worker 쓰레드가 종료할때까지 wait 할 수 있다.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QThread *thread);
    virtual ~Worker();

public slots:
    void doWork();

private:
    QThread*    m_pThread;
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_btnStart_clicked();
    void on_btnWait_clicked();

private:
    Ui::MainWindow *ui;

    QThread*    m_pThread;
    Worker*     m_pWorker;
};
#endif // MAINWINDOW_H



#include "mainwindow.h"
#include "ui_mainwindow.h"

Worker::Worker(QThread *thread)
{
    m_pThread = thread;
}
Worker::~Worker()
{
}
void Worker::doWork()
{
    int count = 0;
    while (count++ < 10) {
        printf("do work\n");
        QThread::sleep(1);
    }

    m_pThread->exit();    // 인수로 받은 QThread의 exit을 호출해야 함
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_pThread = new QThread();
    m_pWorker = new Worker(m_pThread);
    m_pWorker->moveToThread(m_pThread);

    connect(m_pThread, SIGNAL(started()), m_pWorker, SLOT(doWork()));
}
MainWindow::~MainWindow()
{
    delete m_pThread;
    delete m_pWorker;
    delete ui;
}

void MainWindow::on_btnStart_clicked()
{
    if (m_pThread->isRunning()) {
        return;
    }

    m_pThread->start();
}

void MainWindow::on_btnWait_clicked()
{
    printf("wait start\n");
    m_pThread->wait();
    printf("wait finished\n");
}

위와 같이 Worker는 QThread를 인수로 받아서 쓰레드 종료시 exit() 을 호출하면 wait() 함수에서 
종료시점에 동기화를 맞출수 있다