2015-11-06 4 views
1

Исходя из среды Java (в частности, Android) У меня никогда не возникало проблем с выполнением некоторого кода в новом потоке без блокировки основного потока. Как я должен работать с C++, теперь я наткнулся на проблему.C++ serial thread executor

код клиента выполняет мой родной (C++) код через JNI:

JNIEXPORT jbyteArray JNICALL 
Java_com_native_project_NativeInterface_processData(JNIEnv *env, jobject instance, jbyteArray inputData_) { 
    vector<unsigned char> inputData = jbyteArrayToBytes(env, inputData_); 
    const vector<unsigned char> &result = getDataProcessor(env, instance).processData(inputData); 
    return bytesTojbyteArray(env, result); 
} 

DataProcessor getDataProcessor(JNIEnv *env, jobject instance) { 
    return DataProcessor(env, instance); 
} 

Тогда в моем DataProcessor я хочу сделать два thigs:

  • обрабатывать данные и вернуть его как можно скорее
  • записывает данные в журнал активности (например, базу данных) без задержки ответа (поэтому сначала верните ответ и затем зарегистрируйте данные)

Пример кода:

class BasicAsync { 
private: 
    void logToDB(const vector<unsigned char> &inputData) { 
     // connect to DB and write data to it 
    } 

    vector<unsigned char> compute(const vector<unsigned char> &inputData) { 
     vector<unsigned char> result = vector<unsigned char>(); 
     // rocket-science computation in here 
     return result; 
    } 

public: 
    vector<unsigned char> processData(const vector<unsigned char> &inputData) { 
     // perform data computation and produce output 
     vector<unsigned char> result = compute(inputData); 

     // create a thread that writes the data to activity log without delaying the response return 
     logToDB(inputData); 

     //return result while data is written to activity log 
     return result; 
    } 
} 

Мои главные concers являются:

  1. Можно ли в C++ (я использую C++ 11)?
  2. Если требуется время, чтобы записать данные в базу данных, что происходит с объектом DataProcessor в течение этого времени (так как он должен быть уничтожен после ответа на ответ через JNI по мере того, как заканчивается его срок действия), может быть, я чего-то не хватает)?
  3. Есть ли какой-либо исполнитель серийных потоков, чтобы я мог написать несколько вещей в базу данных (они будут помещены в очередь FIFO и сохранены в последовательности в том же потоке)?
+0

Я понятия не имею о jni, b ut вы можете создать поток, который записывается в базу данных и немедленно отделять его. – MikeMB

+0

Однако имейте в виду, что создание потока - дорогостоящая операция, поэтому наличие одного выделенного потока для ведения журнала, как вы предположили, безусловно, будет более эффективным. – MikeMB

ответ

2
  1. Да
  2. Рассмотрим варианта Active Object Pattern реализовать последовательные очереди выполнения, чтобы сделать вашу затянувшуюся работу, которая должна быть сериализована:
#include <thread> 
#include <mutex> 
#include <functional> 
#include <queue> 

class SerialExecutionQueue 
{ 
public: 
    typedef std::function<void()> QueueItem; 

    SerialExecutionQueue() : 
    m_shouldQuit(false), 
    m_executor([this]() 
     { 
      executor(); 
     }) 
    { 

    } 

    void enqueueWork(QueueItem item) 
    { 
     { 
      std::lock_guard<std::mutex> l(m_mutex); 
      m_queue.push(item); 
     } 
     m_cv.notify_all(); 
    } 

    void executor() 
    { 
     while (!m_shouldQuit) 
     { 
      std::unique_lock<std::mutex> lock(m_mutex); 
      while (m_queue.size()) 
      { 
       auto item = m_queue.front(); 
       m_queue.pop(); 
       m_mutex.unlock(); 
       item(); 
       m_mutex.lock(); 
      } 
      m_cv.wait(lock); 
     } 
    } 

private: 
    bool     m_shouldQuit; 
    std::condition_variable m_cv; 
    std::mutex    m_mutex; 
    std::queue<QueueItem> m_queue; 
    std::thread    m_executor; 
}; 
int main(int argc, const char * argv[]) 
{ 

    SerialExecutionQueue queue; 

    queue.enqueueWork([]() 
      { 
       std::cout << "Did some work 1" <<std::endl; 
      }); 


    queue.enqueueWork([]() 
      { 
       std::cout << "Did some work 2" <<std::endl; 
      }); 

    sleep(1); 

    queue.enqueueWork([]() 
      { 
       std::cout << "Did some work 3" <<std::endl; 
      }); 

    sleep(10); 
    return 0; 
} 

Выход:

Did some work 1 
Did some work 2 
Did some work 3 
0

До 2011 года нужно было использовать собственные API-интерфейсы, как Pthreads непосредственно или развернуть LIBS сторонних оболочек, как и от повышения, но с 2011 года, C++ предлагает довольно толстый стандартизированный thread интерфейс.

Возможно, вы сначала посмотрите на это сами, попробуйте и добавьте более конкретные вопросы к своему сообщению; Затем я продолжу этот ответ.

Смежные вопросы