Merge pull request #2569 from stweil/thread

Replace propriatary thread data type by std::thread
This commit is contained in:
zdenop 2019-07-15 14:35:04 +02:00 committed by GitHub
commit 852dbe3530
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 43 additions and 98 deletions

View File

@ -24,11 +24,7 @@
#include "imagedata.h"
#include <cinttypes> // for PRId64
#if defined(__MINGW32__)
#include <unistd.h>
#else
#include <thread>
#endif
#include <thread> // for std::thread
#include "allheaders.h" // for pixDestroy, pixGetHeight, pixGetWidth, lept_...
#include "boxread.h" // for ReadMemBoxes
@ -374,13 +370,6 @@ bool ImageData::AddBoxes(const char* box_text) {
return false;
}
// Thread function to call ReCachePages.
void* ReCachePagesFunc(void* data) {
auto* document_data = static_cast<DocumentData*>(data);
document_data->ReCachePages();
return nullptr;
}
DocumentData::DocumentData(const STRING& name)
: document_name_(name),
pages_offset_(-1),
@ -448,7 +437,8 @@ void DocumentData::LoadPageInBackground(int index) {
if (pages_offset_ == index) return;
pages_offset_ = index;
pages_.clear();
SVSync::StartThread(ReCachePagesFunc, this);
std::thread t(&tesseract::DocumentData::ReCachePages, this);
t.detach();
}
// Returns a pointer to the page with the given index, modulo the total
@ -463,11 +453,7 @@ const ImageData* DocumentData::GetPage(int index) {
if (needs_loading) LoadPageInBackground(index);
// We can't directly load the page, or the background load will delete it
// while the caller is using it, so give it a chance to work.
#if defined(__MINGW32__)
sleep(1);
#else
std::this_thread::sleep_for(std::chrono::seconds(1));
#endif
std::this_thread::yield();
}
return page;
}

View File

@ -2,7 +2,6 @@
// File: lstmtester.cpp
// Description: Top-level line evaluation class for LSTM-based networks.
// Author: Ray Smith
// Created: Wed Nov 23 11:18:06 PST 2016
//
// (C) Copyright 2016, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
@ -16,6 +15,7 @@
// limitations under the License.
///////////////////////////////////////////////////////////////////////
#include <thread> // for std::thread
#include "lstmtester.h"
#include "genericvector.h"
@ -70,7 +70,8 @@ STRING LSTMTester::RunEvalAsync(int iteration, const double* training_errors,
test_training_errors_ = training_errors;
test_model_mgr_ = model_mgr;
test_training_stage_ = training_stage;
SVSync::StartThread(&LSTMTester::ThreadFunc, this);
std::thread t(&LSTMTester::ThreadFunc, this);
t.detach();
} else {
UnlockRunning();
}
@ -123,21 +124,15 @@ STRING LSTMTester::RunEvalSync(int iteration, const double* training_errors,
return result;
}
// Static helper thread function for RunEvalAsync, with a specific signature
// required by SVSync::StartThread. Actually a member function pretending to
// be static, its arg is a this pointer that it will cast back to LSTMTester*
// to call RunEvalSync using the stored args that RunEvalAsync saves in *this.
// Helper thread function for RunEvalAsync.
// LockIfNotRunning must have returned true before calling ThreadFunc, and
// it will call UnlockRunning to release the lock after RunEvalSync completes.
/* static */
void* LSTMTester::ThreadFunc(void* lstmtester_void) {
LSTMTester* lstmtester = static_cast<LSTMTester*>(lstmtester_void);
lstmtester->test_result_ = lstmtester->RunEvalSync(
lstmtester->test_iteration_, lstmtester->test_training_errors_,
lstmtester->test_model_mgr_, lstmtester->test_training_stage_,
void LSTMTester::ThreadFunc() {
test_result_ = RunEvalSync(
test_iteration_, test_training_errors_,
test_model_mgr_, test_training_stage_,
/*verbosity*/ 0);
lstmtester->UnlockRunning();
return lstmtester_void;
UnlockRunning();
}
// Returns true if there is currently nothing running, and takes the lock

View File

@ -62,13 +62,10 @@ class LSTMTester {
int verbosity);
private:
// Static helper thread function for RunEvalAsync, with a specific signature
// required by SVSync::StartThread. Actually a member function pretending to
// be static, its arg is a this pointer that it will cast back to LSTMTester*
// to call RunEvalSync using the stored args that RunEvalAsync saves in *this.
// Helper thread function for RunEvalAsync.
// LockIfNotRunning must have returned true before calling ThreadFunc, and
// it will call UnlockRunning to release the lock after RunEvalSync completes.
static void* ThreadFunc(void* lstmtester_void);
void ThreadFunc();
// Returns true if there is currently nothing running, and takes the lock
// if there is nothing running.
bool LockIfNotRunning();

View File

@ -24,6 +24,7 @@
#include <map>
#include <mutex> // for std::mutex
#include <string>
#include <thread> // for std::thread
#include <utility>
#include <vector>
@ -80,7 +81,7 @@ SVEventHandler::~SVEventHandler() = default;
/// to the client. It basically loops through messages, parses them to events
/// and distributes it to the waiting handlers.
/// It is run from a different thread and synchronizes via SVSync.
void* ScrollView::MessageReceiver(void* a) {
void ScrollView::MessageReceiver() {
int counter_event_id = 0; // ongoing counter
char* message = nullptr;
// Wait until a new message appears in the input stream_.
@ -177,7 +178,6 @@ void* ScrollView::MessageReceiver(void* a) {
message = ScrollView::GetStream()->Receive();
} while (message == nullptr);
}
return nullptr;
}
// Table to implement the color index values in the old system.
@ -277,7 +277,8 @@ void ScrollView::Initialize(const char* name, int x_pos, int y_pos, int x_size,
svmap_mu = new std::mutex();
SendRawMessage(
"svmain = luajava.bindClass('com.google.scrollview.ScrollView')\n");
SVSync::StartThread(MessageReceiver, nullptr);
std::thread t(&ScrollView::MessageReceiver);
t.detach();
}
// Set up the variables on the clientside.
@ -312,48 +313,48 @@ void ScrollView::Initialize(const char* name, int x_pos, int y_pos, int x_size,
x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size);
SendRawMessage(message);
SVSync::StartThread(StartEventHandler, this);
std::thread t(&ScrollView::StartEventHandler, this);
t.detach();
}
/// Sits and waits for events on this window.
void* ScrollView::StartEventHandler(void* a) {
auto* sv = static_cast<ScrollView*>(a);
void ScrollView::StartEventHandler() {
SVEvent* new_event;
do {
for (;;) {
stream_->Flush();
sv->semaphore_->Wait();
semaphore_->Wait();
new_event = nullptr;
int serial = -1;
int k = -1;
sv->mutex_->lock();
mutex_->lock();
// Check every table entry if he is is valid and not already processed.
for (int i = 0; i < SVET_COUNT; i++) {
if (sv->event_table_[i] != nullptr &&
(serial < 0 || sv->event_table_[i]->counter < serial)) {
new_event = sv->event_table_[i];
serial = sv->event_table_[i]->counter;
if (event_table_[i] != nullptr &&
(serial < 0 || event_table_[i]->counter < serial)) {
new_event = event_table_[i];
serial = event_table_[i]->counter;
k = i;
}
}
// If we didn't find anything we had an old alarm and just sleep again.
if (new_event != nullptr) {
sv->event_table_[k] = nullptr;
sv->mutex_->unlock();
if (sv->event_handler_ != nullptr) { sv->event_handler_->Notify(new_event); }
event_table_[k] = nullptr;
mutex_->unlock();
if (event_handler_ != nullptr) { event_handler_->Notify(new_event); }
if (new_event->type == SVET_DESTROY) {
// Signal the destructor that it is safe to terminate.
sv->event_handler_ended_ = true;
sv = nullptr;
event_handler_ended_ = true;
delete new_event; // Delete the pointer after it has been processed.
return;
}
delete new_event; // Delete the pointer after it has been processed.
} else {
sv->mutex_->unlock();
mutex_->unlock();
}
// The thread should run as long as its associated window is alive.
} while (sv != nullptr);
return nullptr;
// The thread should run as long as its associated window is alive.
}
}
#endif // GRAPHICS_DISABLED

View File

@ -361,8 +361,8 @@ class ScrollView {
// Send the current buffered polygon (if any) and clear it.
void SendPolygon();
// Start the message receiving thread.
static void* MessageReceiver(void* a);
// Start the message receiving thread.
static void MessageReceiver();
// Place an event into the event_table (synchronized).
void SetEvent(SVEvent* svevent);
@ -373,8 +373,9 @@ class ScrollView {
// Returns the unique, shared network stream.
static SVNetwork* GetStream() { return stream_; }
// Starts a new event handler. Called whenever a new window is created.
static void* StartEventHandler(void* sv);
// Starts a new event handler.
// Called asynchronously whenever a new window is created.
void StartEventHandler();
// Escapes the ' character with a \, so it can be processed by LUA.
char* AddEscapeChars(const char* input);

View File

@ -41,7 +41,6 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <semaphore.h>
#include <csignal>
#include <sys/select.h>
@ -52,39 +51,10 @@
#include <unistd.h>
#endif
// Create new thread.
void SVSync::StartThread(void* (*func)(void*), void* arg) {
#ifdef _WIN32
LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE)func;
DWORD threadid;
CreateThread(nullptr, // default security attributes
0, // use default stack size
f, // thread function
arg, // argument to thread function
0, // use default creation flags
&threadid); // returns the thread identifier
#else
pthread_t helper;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&helper, &attr, func, arg);
#endif
}
#ifndef GRAPHICS_DISABLED
const int kMaxMsgSize = 4096;
// Signals a thread to exit.
void SVSync::ExitThread() {
#ifdef _WIN32
// ExitThread(0);
#else
pthread_exit(nullptr);
#endif
}
// Starts a new process.
void SVSync::StartProcess(const char* executable, const char* args) {
std::string proc;

View File

@ -26,7 +26,6 @@
#ifdef _WIN32
# include "host.h" // also includes windows.h
#else
#include <pthread.h>
#include <semaphore.h>
#endif
@ -36,10 +35,6 @@
/// The SVSync class provides functionality for Thread & Process Creation
class SVSync {
public:
/// Create new thread.
static void StartThread(void *(*func)(void*), void* arg);
/// Signals a thread to exit.
static void ExitThread();
/// Starts a new process.
static void StartProcess(const char* executable, const char* args);
};