Skip to content

Commit

Permalink
fix for stall abort and for too fast stop-start of HidDevReader
Browse files Browse the repository at this point in the history
  • Loading branch information
kmicki committed May 6, 2022
1 parent aa62d52 commit 702d5df
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 120 deletions.
31 changes: 8 additions & 23 deletions inc/hiddev/hiddevreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,18 @@ namespace kmicki::hiddev
// Locks frame for reading.
// If frame is locked for writing, it waits until writing is finished.
// After finishing reading the frame, it is improtant to call UnlockFrame().
frame_t const& GetFrame(void * client = 0);
frame_t const& GetFrame();

frame_t const& Frame();

// Get current frame data.
// Locks frame for reading.
// If frame is locked for writing, it waits until writing is finished.
// Blocks if there was no new frame after last use of GetFrame or GetNewFrame
frame_t const& GetNewFrame(void * client = 0);

// Check if frame is currently being written to.
// True means that GetFrame() will block until writing ends.
bool const& IsFrameLockedForWriting() const;

// Check if frame is locked for reading.
// True means that new frame will not be generated.
// Use UnlockFrame() to unlock it.
bool const& IsFrameLockedForReading() const;

// Lock frame for reading.
// If frame is locked for writing, it waits until writing is finished.
void LockFrame(void * client = 0);
frame_t const& GetNewFrame();

// Unlock frame.
void UnlockFrame(void * client = 0);
void UnlockFrame();

void Start();

Expand All @@ -75,15 +62,16 @@ namespace kmicki::hiddev

bool IsStopping();

std::mutex frameMutex;

protected:

bool frameDelivered;

frame_t frame;

int frameLen;
std::string inputFilePath;
bool preReadingLock;
bool readingLock;
bool writingLock;

std::chrono::microseconds scanPeriod;

Expand All @@ -109,10 +97,7 @@ namespace kmicki::hiddev

std::unique_ptr<std::ifstream> inputStream;

std::set<void *> clients;
std::set<void *> clientLocks;

std::mutex lockMutex, clientsMutex, startStopMutex;
std::mutex startStopMutex;

void LossAnalysis(uint32_t diff);

Expand Down
2 changes: 2 additions & 0 deletions src/cemuhook/cemuhookserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ namespace kmicki::cemuhook
{
stopSending = true;
sendThread.get()->join();
std::this_thread::sleep_for(std::chrono::seconds(1));
sendThread.reset();
}
if(sendThread.get() == nullptr)
Expand All @@ -206,6 +207,7 @@ namespace kmicki::cemuhook
std::cout << "Cemuhook Server: No packet from client for some time. Stop sending data." << std::endl;
stopSending = true;
sendThread.get()->join();
std::this_thread::sleep_for(std::chrono::seconds(1));
sendThread.reset();
}
sendTimeout = 0;
Expand Down
140 changes: 47 additions & 93 deletions src/hiddev/hiddevreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ namespace kmicki::hiddev

HidDevReader::HidDevReader(int hidNo, int _frameLen, int scanTime)
: frameLen(_frameLen),
frame(_frameLen),
preReadingLock(false),readingLock(false),writingLock(false),
frame(_frameLen),frameDelivered(false),
stopTask(false),stopMetro(false),stopRead(false),
scanPeriod(scanTime),
inputStream(nullptr),
clients(),clientLocks(),
lockMutex(),clientsMutex(),startStopMutex(),
frameMutex(),startStopMutex(),
v(),m()
{
if(hidNo < 0) throw std::invalid_argument("hidNo");
Expand Down Expand Up @@ -84,13 +82,10 @@ namespace kmicki::hiddev
Stop();
}

HidDevReader::frame_t const& HidDevReader::GetFrame(void * client)
HidDevReader::frame_t const& HidDevReader::GetFrame()
{
LockFrame(client);
clientsMutex.lock();
if(clients.find(client) == clients.end())
clients.insert(client);
clientsMutex.unlock();
frameMutex.lock();
frameDelivered = true;
return frame;
}

Expand All @@ -99,45 +94,15 @@ namespace kmicki::hiddev
return frame;
}

HidDevReader::frame_t const& HidDevReader::GetNewFrame(void * client)
HidDevReader::frame_t const& HidDevReader::GetNewFrame()
{
while(clients.find(client) != clients.end() && !stopTask) std::this_thread::sleep_for(std::chrono::microseconds(100));
return GetFrame(client);
while(frameDelivered && !stopTask) std::this_thread::sleep_for(std::chrono::microseconds(100));
return GetFrame();
}

bool const& HidDevReader::IsFrameLockedForWriting() const
void HidDevReader::UnlockFrame()
{
return writingLock;
}
bool const& HidDevReader::IsFrameLockedForReading() const
{
return readingLock;
}

void HidDevReader::LockFrame(void* client)
{
lockMutex.lock();
if(clientLocks.find(client) == clientLocks.end())
clientLocks.insert(client);
if(! preReadingLock && ! readingLock)
{
preReadingLock = true;
while(writingLock) ;
readingLock = true;
preReadingLock = false;
}
lockMutex.unlock();
}

void HidDevReader::UnlockFrame(void * client)
{
lockMutex.lock();
std::set<void*>::iterator iter;
while((iter = clientLocks.find(client)) != clientLocks.end())
clientLocks.erase(iter);
if(clientLocks.size() == 0)
readingLock = false;
lockMutex.unlock();
frameMutex.unlock();
}

void HidDevReader::reconnectInput(std::ifstream & stream, std::string path)
Expand Down Expand Up @@ -295,63 +260,52 @@ namespace kmicki::hiddev
reconnectInput(input,inputFilePath);
}
else {
if( readingLock || preReadingLock )
std::this_thread::sleep_for(std::chrono::microseconds(200));
frameMutex.lock();
// Start processing data in a separate thread unless previous processing has not finished
if( !readingLock && !preReadingLock )
{
writingLock = true;
auto bufProcess = buf;
// swap buffers
if(buf == &buf1_1)
buf = &buf1_2;
else
buf = &buf1_1;
{
std::unique_lock<std::mutex> lock(m);
rdy = false;
if(tick && wait)
v.notify_one();
}

processData(*buf);

uint32_t * newInc = reinterpret_cast<uint32_t *>(frame.data()+4);
uint32_t diff = *newInc - lastInc;
LossAnalysis(diff);
auto bufProcess = buf;
// swap buffers
if(buf == &buf1_1)
buf = &buf1_2;
else
buf = &buf1_1;
{
std::unique_lock<std::mutex> lock(m);
rdy = false;
if(tick && wait)
v.notify_one();
}

processData(*buf);

if(diff > 1 && lastInc > 0 && diff <= 40)
{
*newInc = lastInc+1;
// Fill with generated frames to avoid jitter
auto fillPeriod = std::chrono::microseconds(3200/(diff-1));//3000/(diff-1));
uint32_t * newInc = reinterpret_cast<uint32_t *>(frame.data()+4);
uint32_t diff = *newInc - lastInc;
LossAnalysis(diff);

// Flag - replicated frames
frame[0] = 0xDD;
if(diff > 1 && lastInc > 0 && diff <= 40)
{
*newInc = lastInc+1;
// Fill with generated frames to avoid jitter
auto fillPeriod = std::chrono::microseconds(3200/(diff-1));//3000/(diff-1));

for (int i = 0; i < diff-1; i++)
{
writingLock=false;
clientsMutex.lock();
clients.clear();
clientsMutex.unlock();
std::this_thread::sleep_for(fillPeriod);
if( !readingLock && !preReadingLock )
writingLock = true;
++(*newInc);
}
// Flag - replicated frames
frame[0] = 0xDD;

frame[0] = 0x01;
for (int i = 0; i < diff-1; i++)
{
frameDelivered = false;
frameMutex.unlock();
std::this_thread::sleep_for(fillPeriod);
frameMutex.lock();
++(*newInc);
}
lastInc = *newInc;

writingLock = false;

clientsMutex.lock();
clients.clear();
clientsMutex.unlock();

frame[0] = 0x01;
}
lastInc = *newInc;

frameDelivered = false;
frameMutex.unlock();
}
}
stopRead = stopMetro = true;
Expand Down
4 changes: 3 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bool showIncrement = false;
#define FRAME_LEN 64
#define SCAN_PERIOD_US 3900

#define VERSION "1.5"
#define VERSION "1.6"

#define VID 0x28de
#define PID 0x1205
Expand Down Expand Up @@ -72,6 +72,8 @@ int main()
}
if(!reader.IsStarted() && !reader.IsStopping())
lastInc = 0;
else
lastInc = newInc;
if(!reader.IsStopping())
stopping = 0;
}
Expand Down
6 changes: 3 additions & 3 deletions src/sdgyrodsu/cemuhookadapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,20 @@ namespace kmicki::sdgyrodsu
static uint32_t lastInc = 0;
while(true)
{
auto const& frame = reader.GetNewFrame(this);
auto const& frame = reader.GetNewFrame();

auto const& inc = *reinterpret_cast<uint32_t const*>(frame.data()+4);

if(inc <= lastInc && lastInc-inc < 40)
{
reader.UnlockFrame(this);
reader.UnlockFrame();
}
else
{
lastInc = inc;

SetMotionData(GetSdFrame(frame),data);
reader.UnlockFrame(this);
reader.UnlockFrame();
return data;
}
}
Expand Down

0 comments on commit 702d5df

Please sign in to comment.